wukong引擎源码分析之索引——part 3 文档评分 无非就是将docid对应的fields信息存储起来,为搜索结果rank评分用

简介:

之前的文章分析过,接受索引请求处理的代码在segmenter_worker.go里:

复制代码
复制代码
func (engine *Engine) segmenterWorker() {
    for {
        request := <-engine.segmenterChannel //关键

        tokensMap := make(map[string][]int)
        numTokens := 0
        if !engine.initOptions.NotUsingSegmenter && request.data.Content != "" {
            // 当文档正文不为空时,优先从内容分词中得到关键词
            segments := engine.segmenter.Segment([]byte(request.data.Content))
            for _, segment := range segments {
                token := segment.Token().Text()
                if !engine.stopTokens.IsStopToken(token) {
                    tokensMap[token] = append(tokensMap[token], segment.Start())
                }
            }
            numTokens = len(segments)
        } else {
            // 否则载入用户输入的关键词
            for _, t := range request.data.Tokens {
                if !engine.stopTokens.IsStopToken(t.Text) {
                    tokensMap[t.Text] = t.Locations
                }
            }
            numTokens = len(request.data.Tokens)
        }

        // 加入非分词的文档标签
        for _, label := range request.data.Labels {
            if !engine.initOptions.NotUsingSegmenter {
                if !engine.stopTokens.IsStopToken(label) {
                    tokensMap[label] = []int{}
                }
            } else {
                tokensMap[label] = []int{}
            }
        }

        indexerRequest := indexerAddDocumentRequest{
            document: &types.DocumentIndex{
                DocId:       request.docId,
                TokenLength: float32(numTokens),
                Keywords:    make([]types.KeywordIndex, len(tokensMap)),
            },
        }
        iTokens := 0
        for k, v := range tokensMap {
            indexerRequest.document.Keywords[iTokens] = types.KeywordIndex{
                Text: k,
                // 非分词标注的词频设置为0,不参与tf-idf计算
                Frequency: float32(len(v)),
                Starts:    v}
            iTokens++
        }

        var dealDocInfoChan = make(chan bool, 1)

        indexerRequest.dealDocInfoChan = dealDocInfoChan
        engine.indexerAddDocumentChannels[request.shard] <- indexerRequest

        rankerRequest := rankerAddDocRequest{
            docId:           request.docId,
            fields:          request.data.Fields,
            dealDocInfoChan: dealDocInfoChan,
        }
        engine.rankerAddDocChannels[request.shard] <- rankerRequest
    }
}
复制代码
复制代码

上面代码的作用就是在统计词频和单词位置(注意:tag也是作为搜索的单词,不过其词频是0,而无法参与tf-idf计算),并封装为indexerRequest,发送给engine.indexerAddDocumentChannels[request.shard]

此外,红色部分代码是在为文档评分做准备,engine/ranker_worker.go:

复制代码
func (engine *Engine) rankerAddDocWorker(shard int) {                                                                                                                                           
    for {
        request := <-engine.rankerAddDocChannels[shard] //关键
        docInfo := engine.rankers[shard].AddDoc(request.docId, request.fields, request.dealDocInfoChan)                                                                                         
        // save
        if engine.initOptions.UsePersistentStorage {
            engine.persistentStorageIndexDocumentChannels[shard] <- persistentStorageIndexDocumentRequest{                                                                                      
                typ:     "info",                
                docId:   request.docId,         
                docInfo: docInfo,           
            }                  
        }
    }
}
复制代码

AddDoc无非就是将docid对应的fields信息存储起来,为搜索结果rank评分用!

复制代码
// 给某个文档添加评分字段
func (ranker *Ranker) AddDoc(docId uint64, fields interface{}, dealDocInfoChan <-chan bool) *types.DocInfo {
    if ranker.initialized == false {
        log.Fatal("排序器尚未初始化")   
    }

    <-dealDocInfoChan // 等待索引器处理完成

    ranker.DocInfosShard.Lock()
    defer ranker.DocInfosShard.Unlock()
    if _, found := ranker.DocInfosShard.DocInfos[docId]; !found {
        ranker.DocInfosShard.DocInfos[docId] = new(types.DocInfo)
        ranker.DocInfosShard.NumDocuments++
    }
    ranker.DocInfosShard.DocInfos[docId].Fields = fields
    return ranker.DocInfosShard.DocInfos[docId]
}
复制代码

 














本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/bonelee/p/6582369.html,如需转载请自行联系原作者


相关文章
|
测试技术
Elasticsearch查询结果如何防止搜索词在文档中多次出现时分数增加?
Elasticsearch查询结果如何防止搜索词在文档中多次出现时分数增加?
97 1
|
JSON API 开发者
如何使用分类ID参数过滤搜索词推荐数据?
一、背景介绍 阿里巴巴中国站的搜索词推荐数据对于开发者来说具有重要的参考价值。通过使用获得搜索词推荐 API,开发者可以获取到用户在平台上的搜索行为数据,了解用户的需求和行为,优化产品和服务。在获取搜索词推荐数据的过程中,有时候需要对数据进行更精细的过滤和分析。其中,分类ID参数是一个非常重要的过滤条件,可以帮助开发者更好地筛选数据。本文将详细介绍如何使用分类ID参数过滤搜索词推荐数据,帮助读者更好地理解和使用该 API。
|
SQL Java
白话Elasticsearch04- 结构化搜索之使用terms query搜索多个值以及多值搜索结果优化
白话Elasticsearch04- 结构化搜索之使用terms query搜索多个值以及多值搜索结果优化
531 0
|
SQL
白话Elasticsearch05- 结构化搜索之使用range query来进行范围过滤
白话Elasticsearch05- 结构化搜索之使用range query来进行范围过滤
122 0
|
Java Apache 索引
白话Elasticsearch10-深度探秘搜索技术之基于dis_max实现best fields策略进行多字段搜索
白话Elasticsearch10-深度探秘搜索技术之基于dis_max实现best fields策略进行多字段搜索
96 0
|
SQL JSON 自然语言处理
白话Elasticsearch01- 结构化搜索之使用term query来搜索数据
白话Elasticsearch01- 结构化搜索之使用term query来搜索数据
303 0
|
SQL 索引
白话Elasticsearch03- 结构化搜索之基于bool组合多个filter条件来搜索数据
白话Elasticsearch03- 结构化搜索之基于bool组合多个filter条件来搜索数据
304 0
|
缓存 自然语言处理 数据挖掘
白话Elasticsearch50-深入聚合数据分析之基于doc values正排索引的聚合内部原理
白话Elasticsearch50-深入聚合数据分析之基于doc values正排索引的聚合内部原理
115 0
|
自然语言处理 算法 数据挖掘
白话Elasticsearch51-深入聚合数据分析之text field聚合以及fielddata原理
白话Elasticsearch51-深入聚合数据分析之text field聚合以及fielddata原理
125 0