migrate from github
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/config"
|
||||
"github.com/XingfenD/yoresee_doc/internal/model"
|
||||
"github.com/XingfenD/yoresee_doc/pkg/key"
|
||||
"github.com/XingfenD/yoresee_doc/pkg/storage"
|
||||
)
|
||||
|
||||
const defaultSearchIndexPrefix = "yoresee_doc"
|
||||
|
||||
type DocumentSearchRequest struct {
|
||||
Keyword string
|
||||
UserID *int64
|
||||
KnowledgeID *int64
|
||||
ListOwnDoc bool
|
||||
DocType *string
|
||||
Tags []string
|
||||
CreateTimeRangeStart *string
|
||||
CreateTimeRangeEnd *string
|
||||
UpdateTimeRangeStart *string
|
||||
UpdateTimeRangeEnd *string
|
||||
Size int
|
||||
}
|
||||
|
||||
func SearchDocumentIDs(ctx context.Context, req DocumentSearchRequest) ([]int64, error) {
|
||||
if storage.ES == nil {
|
||||
return nil, fmt.Errorf("elasticsearch client is nil")
|
||||
}
|
||||
return storage.ES.SearchIDs(ctx, DocumentIndexName(), BuildDocumentSearchBody(req))
|
||||
}
|
||||
|
||||
func UpsertDocument(ctx context.Context, doc *model.Document) error {
|
||||
if doc == nil {
|
||||
return fmt.Errorf("document is nil")
|
||||
}
|
||||
if storage.ES == nil {
|
||||
return fmt.Errorf("elasticsearch client is nil")
|
||||
}
|
||||
return storage.ES.UpsertDocument(ctx, DocumentIndexName(), strconv.FormatInt(doc.ID, 10), BuildDocumentIndexBody(doc))
|
||||
}
|
||||
|
||||
func DocumentIndexName() string {
|
||||
prefix := defaultSearchIndexPrefix
|
||||
if config.GlobalConfig != nil {
|
||||
configPrefix := strings.TrimSpace(config.GlobalConfig.Elasticsearch.IndexPrefix)
|
||||
if configPrefix != "" {
|
||||
prefix = configPrefix
|
||||
}
|
||||
}
|
||||
return key.KeyESDocumentIndex(prefix)
|
||||
}
|
||||
|
||||
func BuildDocumentSearchBody(req DocumentSearchRequest) map[string]interface{} {
|
||||
size := req.Size
|
||||
if size <= 0 {
|
||||
size = 5000
|
||||
}
|
||||
if size > 10000 {
|
||||
size = 10000
|
||||
}
|
||||
|
||||
must := []map[string]interface{}{}
|
||||
if strings.TrimSpace(req.Keyword) != "" {
|
||||
must = append(must, map[string]interface{}{
|
||||
"multi_match": map[string]interface{}{
|
||||
"query": strings.TrimSpace(req.Keyword),
|
||||
"fields": []string{"title^3", "summary^2", "content"},
|
||||
"type": "best_fields",
|
||||
"operator": "and",
|
||||
"fuzziness": "AUTO",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
filter := []map[string]interface{}{}
|
||||
mustNot := []map[string]interface{}{}
|
||||
if req.UserID != nil {
|
||||
filter = append(filter, map[string]interface{}{
|
||||
"term": map[string]interface{}{"user_id": *req.UserID},
|
||||
})
|
||||
}
|
||||
if req.ListOwnDoc {
|
||||
mustNot = append(mustNot, map[string]interface{}{
|
||||
"exists": map[string]interface{}{"field": "knowledge_id"},
|
||||
})
|
||||
}
|
||||
if req.KnowledgeID != nil {
|
||||
filter = append(filter, map[string]interface{}{
|
||||
"term": map[string]interface{}{"knowledge_id": *req.KnowledgeID},
|
||||
})
|
||||
}
|
||||
if req.DocType != nil && strings.TrimSpace(*req.DocType) != "" {
|
||||
filter = append(filter, map[string]interface{}{
|
||||
"term": map[string]interface{}{"type": strings.TrimSpace(*req.DocType)},
|
||||
})
|
||||
}
|
||||
for _, tag := range req.Tags {
|
||||
tag = strings.TrimSpace(tag)
|
||||
if tag == "" {
|
||||
continue
|
||||
}
|
||||
filter = append(filter, map[string]interface{}{
|
||||
"term": map[string]interface{}{"tags.keyword": tag},
|
||||
})
|
||||
}
|
||||
|
||||
rangeCreated := map[string]interface{}{}
|
||||
if req.CreateTimeRangeStart != nil && strings.TrimSpace(*req.CreateTimeRangeStart) != "" {
|
||||
rangeCreated["gte"] = strings.TrimSpace(*req.CreateTimeRangeStart)
|
||||
}
|
||||
if req.CreateTimeRangeEnd != nil && strings.TrimSpace(*req.CreateTimeRangeEnd) != "" {
|
||||
rangeCreated["lte"] = strings.TrimSpace(*req.CreateTimeRangeEnd)
|
||||
}
|
||||
if len(rangeCreated) > 0 {
|
||||
filter = append(filter, map[string]interface{}{
|
||||
"range": map[string]interface{}{"created_at": rangeCreated},
|
||||
})
|
||||
}
|
||||
|
||||
rangeUpdated := map[string]interface{}{}
|
||||
if req.UpdateTimeRangeStart != nil && strings.TrimSpace(*req.UpdateTimeRangeStart) != "" {
|
||||
rangeUpdated["gte"] = strings.TrimSpace(*req.UpdateTimeRangeStart)
|
||||
}
|
||||
if req.UpdateTimeRangeEnd != nil && strings.TrimSpace(*req.UpdateTimeRangeEnd) != "" {
|
||||
rangeUpdated["lte"] = strings.TrimSpace(*req.UpdateTimeRangeEnd)
|
||||
}
|
||||
if len(rangeUpdated) > 0 {
|
||||
filter = append(filter, map[string]interface{}{
|
||||
"range": map[string]interface{}{"updated_at": rangeUpdated},
|
||||
})
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"size": size,
|
||||
"_source": []string{
|
||||
"id",
|
||||
},
|
||||
"query": map[string]interface{}{
|
||||
"bool": map[string]interface{}{
|
||||
"must": must,
|
||||
"filter": filter,
|
||||
"must_not": mustNot,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func BuildDocumentIndexBody(doc *model.Document) map[string]interface{} {
|
||||
payload := map[string]interface{}{
|
||||
"id": doc.ID,
|
||||
"external_id": doc.ExternalID,
|
||||
"title": doc.Title,
|
||||
"summary": doc.Summary,
|
||||
"content": doc.Content,
|
||||
"type": doc.Type,
|
||||
"user_id": doc.UserID,
|
||||
"tags": doc.Tags,
|
||||
"created_at": doc.CreatedAt.Format(time.RFC3339),
|
||||
"updated_at": doc.UpdatedAt.Format(time.RFC3339),
|
||||
}
|
||||
if doc.KnowledgeID != nil {
|
||||
payload["knowledge_id"] = *doc.KnowledgeID
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func BuildDocumentIndexMapping() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"mappings": map[string]interface{}{
|
||||
"properties": map[string]interface{}{
|
||||
"id": map[string]interface{}{
|
||||
"type": "long",
|
||||
},
|
||||
"external_id": map[string]interface{}{
|
||||
"type": "keyword",
|
||||
},
|
||||
"title": map[string]interface{}{
|
||||
"type": "text",
|
||||
},
|
||||
"summary": map[string]interface{}{
|
||||
"type": "text",
|
||||
},
|
||||
"content": map[string]interface{}{
|
||||
"type": "text",
|
||||
},
|
||||
"type": map[string]interface{}{
|
||||
"type": "keyword",
|
||||
},
|
||||
"user_id": map[string]interface{}{
|
||||
"type": "long",
|
||||
},
|
||||
"knowledge_id": map[string]interface{}{
|
||||
"type": "long",
|
||||
},
|
||||
"tags": map[string]interface{}{
|
||||
"type": "keyword",
|
||||
},
|
||||
"created_at": map[string]interface{}{
|
||||
"type": "date",
|
||||
},
|
||||
"updated_at": map[string]interface{}{
|
||||
"type": "date",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user