package engine

import (
    "github.com/huichen/wukong/types"
)

type segmenterRequest struct {
    docId       uint64
    hash        uint32
    data        types.DocumentIndexData
    forceUpdate bool
}

func (engine *Engine) segmenterWorker() {
    for {
        request := <-engine.segmenterChannel
        if request.docId == 0 {
            if request.forceUpdate {
                for i := 0; i < engine.initOptions.NumShards; i++ {
                    engine.indexerAddDocChannels[i] <- indexerAddDocumentRequest{forceUpdate: true}
                }
            }
            continue
        }

        shard := engine.getShard(request.hash)
        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) {
                    //当正文中已存在关键字时,若不判断,位置信息将会丢失
                    if _, ok := tokensMap[label]; !ok {
                        tokensMap[label] = []int{}
                    }
                }
            } else {
                //当正文中已存在关键字时,若不判断,位置信息将会丢失
                if _, ok := tokensMap[label]; !ok {
                    tokensMap[label] = []int{}
                }
            }
        }

        indexerRequest := indexerAddDocumentRequest{
            document: &types.DocumentIndex{
                DocId:       request.docId,
                TokenLength: float32(numTokens),
                Keywords:    make([]types.KeywordIndex, len(tokensMap)),
            },
            forceUpdate: request.forceUpdate,
        }
        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++
        }

        engine.indexerAddDocChannels[shard] <- indexerRequest
        if request.forceUpdate {
            for i := 0; i < engine.initOptions.NumShards; i++ {
                if i == shard {
                    continue
                }
                engine.indexerAddDocChannels[i] <- indexerAddDocumentRequest{forceUpdate: true}
            }
        }
        rankerRequest := rankerAddDocRequest{
            docId: request.docId, fields: request.data.Fields}
        engine.rankerAddDocChannels[shard] <- rankerRequest
    }
}

segmenter_worker.go的更多相关文章

  1. wukong引擎源码分析之索引——part 1 倒排列表本质是有序数组存储

    searcher.IndexDocument(0, types.DocumentIndexData{Content: "此次百度收购将成中国互联网最大并购"}) engine.go ...

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

    之前的文章分析过,接受索引请求处理的代码在segmenter_worker.go里: func (engine *Engine) segmenterWorker() { for { request : ...

随机推荐

  1. LeetCode(56)-Add Binary

    题目: Given two binary strings, return their sum (also a binary string). For example, a = "11&quo ...

  2. 使用vs2010 opencv2.4.4编译release版本程序

    大体上要注意一下几点内容: 1.vc++目录的选择上,库目录选择为opencv目录中的staticlib目录 2.在链接->输入->附加依赖库,中添加,相应的staticlib库目录中的所 ...

  3. ssh优缺点

    面试归来 技术面试官叫我谈谈 ssh优缺点 平时用起来倒是挺顺手..但是从来没有系统的总结过..导致很多点会都没有说出来.. 这次我认真总结了一下... 常说的好处 开源 常说的坏处 配置文件过大我就 ...

  4. java 远程调试方法

    http://wenku.baidu.com/link?url=5p3GZhPcfvM-VOzAFeCjbLeVv0OQrAGJh4HxirqImuK9VxPfmW243T_l5Plj6KdDZB1I ...

  5. TabLayout:另一种Tab的实现方式

    http://blog.csdn.NET/aigestudio/article/details/47155769 在5.0以前我们想要实现像网易新闻客户端那样的的Tab可以有很多种选择: 比如古老的T ...

  6. 使用Swashbuckle构建RESTful风格文档

    本次和大家分享的是Swagger to WebApi的nuget包Swashbuckle:因为项目需要统一api文档的风格,并要支持多种开发语言(C#,java,python),所以首先想到的是swa ...

  7. C++的find函数使用小技巧

    一个小问题:原始字符串如CRYPT,FUNCTION,我要确定里面是否存在CRYPT,于是调用C++的find()函数,结果判断是不存在,怎么回事? 我的判断代码if(strUseFlagsTmp.F ...

  8. longestCommonPrefix

    Description: Write a function to find the longest common prefix string amongst an array of strings. ...

  9. UE4笔记:利用Widget设计一个切换材质功能

    UE4引擎中的Widget蓝图是一个重要的工具,可用于场景中的页面叠加,镜头绑定,场景切换等多处地方,在这里笔者介绍一种利用控件蓝图和场景中物体进行信息交互的方法,直观的体现就是进行物体的材质切换. ...

  10. 从GitHub中整理出来的15个最受欢迎的Python开源框架,你喜欢哪个

    从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python Web应用开发框架 Djang ...