package core

import (
    "github.com/huichen/wukong/types"
    "github.com/huichen/wukong/utils"
    "log"
    "sort"
    "sync"
)

type Ranker struct {
    lock struct {
        sync.RWMutex
        fields map[uint64]interface{}
        docs   map[uint64]bool
    }
    initialized bool
}

func (ranker *Ranker) Init() {
    if ranker.initialized == true {
        log.Fatal("排序器不能初始化两次")
    }
    ranker.initialized = true

    ranker.lock.fields = make(map[uint64]interface{})
    ranker.lock.docs = make(map[uint64]bool)
}

// 给某个文档添加评分字段
func (ranker *Ranker) AddDoc(docId uint64, fields interface{}) {
    if ranker.initialized == false {
        log.Fatal("排序器尚未初始化")
    }

    ranker.lock.Lock()
    ranker.lock.fields[docId] = fields
    ranker.lock.docs[docId] = true
    ranker.lock.Unlock()
}

// 删除某个文档的评分字段
func (ranker *Ranker) RemoveDoc(docId uint64) {
    if ranker.initialized == false {
        log.Fatal("排序器尚未初始化")
    }

    ranker.lock.Lock()
    delete(ranker.lock.fields, docId)
    delete(ranker.lock.docs, docId)
    ranker.lock.Unlock()
}

// 给文档评分并排序
func (ranker *Ranker) Rank(
    docs []types.IndexedDocument, options types.RankOptions, countDocsOnly bool) (types.ScoredDocuments, int) {
    if ranker.initialized == false {
        log.Fatal("排序器尚未初始化")
    }

    // 对每个文档评分
    var outputDocs types.ScoredDocuments
    numDocs := 0
    for _, d := range docs {
        ranker.lock.RLock()
        // 判断doc是否存在
        if _, ok := ranker.lock.docs[d.DocId]; ok {
            fs := ranker.lock.fields[d.DocId]
            ranker.lock.RUnlock()
            // 计算评分并剔除没有分值的文档
            scores := options.ScoringCriteria.Score(d, fs)
            if len(scores) > 0 {
                if !countDocsOnly {
                    outputDocs = append(outputDocs, types.ScoredDocument{
                        DocId:                 d.DocId,
                        Scores:                scores,
                        TokenSnippetLocations: d.TokenSnippetLocations,
                        TokenLocations:        d.TokenLocations})
                }
                numDocs++
            }
        } else {
            ranker.lock.RUnlock()
        }
    }

    // 排序
    if !countDocsOnly {
        if options.ReverseOrder {
            sort.Sort(sort.Reverse(outputDocs))
        } else {
            sort.Sort(outputDocs)
        }
        // 当用户要求只返回部分结果时返回部分结果
        var start, end int
        if options.MaxOutputs != 0 {
            start = utils.MinInt(options.OutputOffset, len(outputDocs))
            end = utils.MinInt(options.OutputOffset+options.MaxOutputs, len(outputDocs))
        } else {
            start = utils.MinInt(options.OutputOffset, len(outputDocs))
            end = len(outputDocs)
        }
        return outputDocs[start:end], numDocs
    }
    return outputDocs, numDocs
}

ranker.go的更多相关文章

  1. 理解AUC

    本文主要讨论了auc的实际意义,并给出了auc的常规计算方法及其证明 转载请注明出处:http://www.cnblogs.com/van19/p/5494908.html 1 ROC曲线和auc 从 ...

  2. RankLib参数翻译

    写在前面,metric2t指标详解: NDCG(Normalized discounted cumulative gain)即DCG/IDCGCG(cumulative gain)DCG(Discou ...

  3. 使用Weka进行数据挖掘

    1.简介 数据挖掘.机器学习这些字眼,在一些人看来,是门槛很高的东西.诚然,如果做算法实现甚至算法优化,确实需要很多背景知识.但事实是,绝大多数数据挖掘工程师,不需要去做算法层面的东西.他们的精力,集 ...

  4. Sphinx 2.2.6 window下安装全过程 未完 持续标记~~~~

    由于在win8.1下安装 选的这个版本 Win64 binaries w/MySQL+PgSQL+libstemmer+id64 support 2.2.6-release 7.3M 下载页面 htt ...

  5. Weka使用介绍

    (转) http://baidutech.blog.51cto.com/4114344/1033714/ 1.简介 数据挖掘.机器学习这些字眼,在一些人看来,是门槛很高的东西.诚然,如果做算法实现甚至 ...

  6. 【Machine Learning】wekaの特征选择简介

    看过这篇博客的都应该明白,特征选择代码实现应该包括3个部分: 搜索算法: 评估函数: 数据: 因此,代码的一般形式为: AttributeSelection attsel = new Attribut ...

  7. weka特征选择(IG、chi-square)

    一.说明 IG是information gain 的缩写,中文名称是信息增益,是选择特征的一个很有效的方法(特别是在使用svm分类时).这里不做详细介绍,有兴趣的可以googling一下. chi-s ...

  8. Codeigniter 集成sphinx搜索 这里采用的是coreseek中文搜索引擎,具体安装请参考官方网站

    先上效果图 加入sphinx类库(/application/libraries/sphinx_client.php) 0001 <?php 0002 0003 // 0004 // $Id: s ...

  9. php 连接测试sphinx

    shpinx.php <?php header("Content-type:text/html;charset=utf-8"); include 'SphinxClient. ...

随机推荐

  1. 二叉树的建立以及遍历的多种实现(python版)

    二叉树是很重要的数据结构,在面试还是日常开发中都是很重要的角色. 首先是建立树的过程,对比C或是C++的实现来讲,其涉及到了较为复杂的指针操作,但是在面向对象的语言中,就不需要考虑指针, 内存等.首先 ...

  2. JS (全局作用域)

    一.全局函数作用域(把变量的声明和函数的声明放在前面) 作用域(scope):一条数据可以在哪个范围中使用. 通常来说,一段程序代码中所用到的数据并不总是有效/可用的,而限定这个数据的可用性的代码范围 ...

  3. Storm 常用命令

    1.启动Nimbus bin/storm nimbus & 2.启动Supervisor bin/storm supervisor & 3.启动UI bin/storm ui & ...

  4. 解密for循环工作机制之迭代器,以及生成器、三元表达式与列表解析、解压序列

    本节内容 1.迭代器协议与for循环 2.三元表达式 3.解压序列 4.列表解析 5.生成器 迭代器协议与for循环 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中下一项, ...

  5. 公司内网搭建代理DNS使用内网域名代替ip地址

    企业场景 一般在企业内部,开发.测试以及预生产都会有一套供开发以及测试人员使用的网络环境.运维人员会为每套环境的相关项目配置单独的Tomcat,然后开放一个端口,以 IP+Port 的形式访问.然而随 ...

  6. 转log4cxx: Could not read configuration file [log4cxx.properties]解决办法

    早上遇到了log4cxx: Could not read configuration file [log4cxx.properties].这个问题.网上搜索后发现是少了log4cxx.properti ...

  7. Oracle VM VirtualBox(一) 快速拷贝一个新的虚拟机

    快速拷贝一个新的虚拟机 一 找到虚拟机vdi文件,复制一份并重命名. 二 修改新虚拟机的UUID 注:不修改创建不了虚拟机,会抛出Oracle VM VirtualBox UUID already e ...

  8. 使用TortoiseGit操作分支的创建与合并

    第一步:创建本地分支 点击右键选择TortoiseGit,选择Create Branch…,在Branch框中填写新分支的名称(若选中”switch to new branch”则直接转到新分支上,省 ...

  9. Mysql-单表查询的操作和注意事项

    一. 单表查询的语法 二 .关键字的执行优先级(重点) 三 .简单查询 四 .WHERE约束 五. 分组查询:GROUP BY 六 .HAVING过滤 七 .查询排序:ORDER BY 八 .限制查询 ...

  10. JavaScript和JQuery的区别

    一.本质上的区别 1.JavaScript 是通过<script></script>标签插入到HTML页面,可由所有的现代浏览器执行的一种轻量级的编程语言. 2.JQuery是 ...