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. obj-c编程02:给类自动合成存取方法

    我们在此篇对obj-c编程01中的Box的例子稍加改动,一是添加的自动合成存取器,二是将Box按照其标准的写法分成3个文件,即头文件Box.h,类实现文件Box.m,以及主文件test.m. 1.Bo ...

  2. OpenCV手写数字字符识别(基于k近邻算法)

    摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...

  3. machine learning 之 Neural Network 3

    整理自Andrew Ng的machine learning课程week6. 目录: Advice for applying machine learning (Decide what to do ne ...

  4. Oracle面试过程中常见的二十个问题

    1.冷备份和热备份的不同点以及各自的优点  解答:热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份.而冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库.热备份的优点在于当备份时, ...

  5. visual studio中如何将string类型值转为BYTE(unsigned char)类型

    昨天困惑一件事,就是手里有个string类型的字符串,像01 23 45 67 89 AB CD EF,根据空格拆分为一个个的子字符串后(如EF),需要放到一个BYTE(typedef unsigne ...

  6. Node笔记四

    异步操作 -Node采用chrome v8 引擎处理javascript脚本 --v8最大特点就是单线程运行,一次只能运行一个任务 -Node大量采用异步操作 --任务不是马上执行,而是插在任务队列的 ...

  7. 详细的<select>下拉列表详解

    我们使用表单下拉列表选择数据,如省.市.县.年.月等数据,我们即可使用下拉菜单表单进行设置.select 我下拉列表菜单标签Option为下拉列表数据标签Value 为Option的数据值(用于数据的 ...

  8. 四年级--python函数基础用法

    一.函数的定义,调用和返回值 1.1 语法 def 函数(参数一,参数二...): ''' 文档注释 ''' 代码逻辑一 代码逻辑二 .... return 返回值 1.2 定义函数的三种形式 说明: ...

  9. java 通过HttpURLConnection与servlet通信

    研究了一天才搞清楚,其实挺简单的,在这里记录下,以便以后参考. 一.创建一个servlet项目 主要包括(WEB-INF)里面有classes文件夹.lib文件夹.web.xml文件. 将写好的ser ...

  10. SpringCloud实战-Ribbon客户端负载均衡

    前面我们已经完成了注册中心和服务提供者两个基础组件.接着介绍使用Spring Cloud Ribbon在客户端负载均衡的调用服务. ribbon 是一个客户端负载均衡器,可以简单的理解成类似于 ngi ...