## bleve 索引库使用 示例
地址: `github.com/blevesearch/bleve` 版本 `2.3.9`
废话不多说,直接上代码
定义一个 client 客户端
```go
package search
import (
"book/config/logger"
"fmt"
"github.com/blevesearch/bleve/v2"
"github.com/blevesearch/bleve/v2/mapping"
)
// 封装的查询客户端
type BevelSearchClient struct {
IndexName string
DocType string
Analyzer string
index bleve.Index
indexMapping *mapping.IndexMappingImpl
documentMapping *mapping.DocumentMapping
}
// 搜索字段结构体
type BevelSearchFiled struct {
FiledName, FiledValue string
}
func (client *BevelSearchClient) CreateIndex() {
// 创建索引
tempIndex, err := bleve.New(client.IndexName, client.indexMapping)
if err != nil {
if err == bleve.ErrorIndexPathExists {
tempIndex, err = bleve.Open(client.IndexName)
} else {
panic(err)
}
}
client.index = tempIndex
logger.Logger.Infoln(fmt.Sprintf("create index: %s success......",
client.IndexName))
}
// CreateIndexMapping 创建索引并将字段映射添加到索引
func (client *BevelSearchClient) CreateIndexMapping() *BevelSearchClient {
client.indexMapping = bleve.NewIndexMapping()
// 重要,索引也要设置分词器,否则不生效
client.indexMapping.DefaultAnalyzer = client.Analyzer
//client.indexMapping.DefaultType
// 将字段映射添加到索引映射中
client.indexMapping.AddDocumentMapping(client.DocType, client.documentMapping)
return client
}
// CreateDocMapping 定义字段映射
func (client *BevelSearchClient) CreateDocMapping(docMapping *mapping.DocumentMapping) *BevelSearchClient {
client.documentMapping = docMapping
return client
}
// AddDoc 添加文档
func (client *BevelSearchClient) AddDoc(id string, data any) {
err := client.index.Index(id, data)
if err != nil {
logger.Logger.Errorln("创建文档失败,失败原因:", err)
}
}
// GetIndex 仅查询时使用
func (client *BevelSearchClient) GetIndex() *BevelSearchClient {
tempIndex, err := bleve.Open(client.IndexName)
if err != nil {
panic(err)
}
client.index = tempIndex
return client
}
func (client *BevelSearchClient) BuildSearchFiled(fields []BevelSearchFiled) *bleve.SearchRequest {
buildQuery := bleve.NewBooleanQuery()
for _, field := range fields {
termQuery := bleve.NewTermQuery(field.FiledValue) // 精确匹配字段值
termQuery.SetField(field.FiledName)
buildQuery.AddMust(termQuery)
}
searchRequest := bleve.NewSearchRequest(buildQuery)
//searchRequest := bleve.NewSearchRequestOptions(query, 10, 0, false) // 分页查询
return searchRequest
}
func (client *BevelSearchClient) search(request *bleve.SearchRequest) *bleve.SearchResult {
request.Fields = []string{"*"}
searchResults, err := client.index.Search(request)
if err != nil {
logger.Logger.Errorln("Error searching:", err)
}
client.index.Close()
return searchResults
}
func (client *BevelSearchClient) FindOne(request *bleve.SearchRequest) map[string]interface{} {
hits := client.search(request)
b := hits.Total > 0
if b {
match := hits.Hits[0]
return match.Fields
}
return nil
}
func (client *BevelSearchClient) FindList(request *bleve.SearchRequest) []map[string]interface{} {
hits := client.search(request)
b := hits.Total > 0
if b {
var res []map[string]interface{}
for _, hit := range hits.Hits {
res = append(res, hit.Fields)
}
return res
}
return nil
}
func (client *BevelSearchClient) DocCount() int64 {
// 执行查询,获取结果总数
count, err := client.index.DocCount()
if err != nil {
panic(err)
}
c := int64(count)
return c
}
func (client *BevelSearchClient) Close() {
defer client.index.Close()
}
```
### 使用-创建索引&往文档里面写入数据
```go
searchClient := search.BevelSearchClient{
IndexName: "pep-book",
DocType: "bookItem",
Analyzer: "simple", // 一定要引入 _ "github.com/blevesearch/bleve/v2/analysis/analyzer/simple"
}
// 定义索引的文档 的mapping, 字段名与结构体的字段做映射
newTextFieldMapping := bleve.NewTextFieldMapping()
// NewKeywordFieldMapping 使用关键字分析器返回文本的字段映射,该分析器基本上不应用任何特定的文本分析。
newTextFieldMapping.Analyzer = searchClient.Analyzer // 默认是 standard 分词器
bookDockMapping.AddFieldMappingsAt("id", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("title", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("xd", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("xk", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("nj", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("cc", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("detail_config_js", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("local_config_js_path", newTextFieldMapping)
bookDockMapping.AddFieldMappingsAt("iterm_image_total", bleve.NewNumericFieldMapping())
// 将数组|切片类型的字段 当做子文档来类型来存储到 book 主文档里面
arrayMapping := bleve.NewDocumentMapping()
arrayMapping.AddFieldMappingsAt("image_url", bleve.NewTextFieldMapping())
arrayMapping.AddFieldMappingsAt("index", bleve.NewNumericFieldMapping()) // If you want to query by index
arrayMapping.AddFieldMappingsAt("local_image_path", bleve.NewTextFieldMapping())
bookDockMapping.AddSubDocumentMapping("iterm_image_list", arrayMapping)
// 注意:子文档的字段访问方式是:iterm_image_list.image_url ,其他字段 以此类推
searchClient.CreateDocMapping(bookDockMapping).CreateIndexMapping().CreateIndex()
// 将数据写入索引中
for _, book := range *list {
searchClient.AddDoc(book.ID, book)
}
```
### 使用-搜索文档
```go
// 从索引中拿数据
request := searchClient.BuildSearchFiled([]search.BevelSearchFiled{
{FiledName: "xd", FiledValue: stage},
{FiledName: "nj", FiledValue: grade},
{FiledName: "xk", FiledValue: subject},
{FiledName: "cc", FiledValue: cc},
})
one := searchClient.GetIndex().FindOne(request)
list := searchClient.GetIndex().FindList(request)
```
### 注意
1. 仅引入 `github.com/blevesearch/bleve/v2` 不行,还需要引入:`github.com/blevesearch/bleve/v2/mapping`
2. 默认装载的分词器只有 `standard` `keyword` ,想使用simple 分词器,需要再创建mapping时,额外引入 `_ "github.com/blevesearch/bleve/v2/analysis/analyzer/simple"`, 否则会提示 未注册分词器
3. document 的 字段分词器 最好和 索引的 mapping 分词器 一致,以免遇到不可预测问题。
### 链接
github: `https://github.com/blevesearch/bleve/tree/v2.3.9`
分词器效果实验地址: `https://bleveanalysis.couchbase.com/analysis`
有疑问加站长微信联系(非本文作者))