package blevex import ( "fmt" "github.com/blevesearch/bleve/v2" "github.com/blevesearch/bleve/v2/mapping" "github.com/yanyiwu/gojieba" "sync" ) // InitAnalyzer 加载自定义分词器(结巴分词) var defaultAnalyzer *mapping.IndexMappingImpl func InitAnalyzer() { indexMapping := bleve.NewIndexMapping() //os.RemoveAll(IndexDir) //// clean index when example finished //defer os.RemoveAll(IndexDir) err := indexMapping.AddCustomTokenizer("gojieba", map[string]interface{}{ "dictpath": gojieba.DICT_PATH, "hmmpath": gojieba.HMM_PATH, "userdictpath": gojieba.USER_DICT_PATH, "idf": gojieba.IDF_PATH, "stop_words": gojieba.STOP_WORDS_PATH, "type": "gojieba", }, ) if err != nil { panic(err) } err = indexMapping.AddCustomAnalyzer("gojieba", map[string]interface{}{ "type": "gojieba", "tokenizer": "gojieba", }, ) if err != nil { panic(err) } indexMapping.DefaultAnalyzer = "gojieba" defaultAnalyzer = indexMapping } var indexMap sync.Map func NewIndex(indexName string) (bleve.Index, error) { if defaultAnalyzer == nil { InitAnalyzer() } index, err := bleve.New(indexName, defaultAnalyzer) if err == bleve.ErrorIndexPathExists { index, err = bleve.Open(indexName) if err != nil { return nil, err } return index, nil } else if err != nil { return nil, err } return index, nil } func LoadIndex(indexName string) (bleve.Index, error) { if v, ok := indexMap.Load(indexName); ok { return v.(bleve.Index), nil } index, err := NewIndex(indexName) if err == nil { indexMap.Store(indexName, index) } return index, err } func Search(indexName string, keyword string, from, size int) (ids []string, total uint64, err error) { index, err := LoadIndex(indexName) if err != nil { return } req := bleve.NewSearchRequest(bleve.NewQueryStringQuery(keyword)) req.From = from req.Size = size res, err := index.Search(req) if err != nil { return nil, 0, err } if res == nil { return } for _, ret := range dealResult(res) { ids = append(ids, ret.Id) } return ids, res.Total, nil } func ComplexSearch(indexName string, keyword string, conditions map[string]interface{}, from, size int) (ids []string, total uint64, err error) { index, err := LoadIndex(indexName) if err != nil { return nil, 0, err } // Create a boolean query with a should clause for fuzzy search boolQuery := bleve.NewBooleanQuery() fuzzyQuery := bleve.NewFuzzyQuery(keyword) fuzzyQuery.SetFuzziness(2) // Set the fuzziness level as needed boolQuery.AddShould(fuzzyQuery) // Add a must clause for category filtering for key, val := range conditions { query := bleve.NewQueryStringQuery(fmt.Sprintf("%s:%s", key, val)) boolQuery.AddMust(query) } req := bleve.NewSearchRequest(boolQuery) req.From = from req.Size = size res, err := index.Search(req) if err != nil { return nil, 0, err } if res == nil { return } for _, ret := range dealResult(res) { ids = append(ids, ret.Id) } return ids, res.Total, nil } type Result struct { Id string `json:"id"` Score float64 `json:"score"` } func dealResult(res *bleve.SearchResult) []Result { var results []Result for _, item := range res.Hits { results = append(results, Result{item.ID, item.Score}) } return results }