首先声明:我对Lucene.Net并不熟悉,但搜索确实是分词的一个重要应用,所以这里还是尝试将两者集成起来,也许对你有一参考。

看到了两个中文分词与Lucene.Net的集成项目:Lucene.Net.Analysis.PanGuLucene.Net.Analysis.MMSeg,参考其中的代码实现了最简单的集成:jiebaForLuceneNet。下面给出简单的介绍。

1、JiebaTokenizer

主要的集成点是自定义一个Tokenizer的子类,此时必须要实现它的抽象方法IncrementToken,该方法用于对文本流中的文本生成的token进行遍历,这正是分词组件发挥作用的地方。

public override bool IncrementToken()
{
ClearAttributes();
position++;
if (position < tokens.Count)
{
var token = tokens[position];
termAtt.SetTermBuffer(token.Word);
offsetAtt.SetOffset(token.StartIndex, token.EndIndex);
typeAtt.Type = "Jieba";
return true;
} End();
return false;
}

termAtt和offsetAtt所在的两行代码需要用到每一个token的词本身、起始索引和终止索引,而这三个值恰好是JiebaSegmenter.Tokenize方法所实现的,所以只要在初始化JiebaTokenizer时使用:

tokens = segmenter.Tokenize(text, TokenizerMode.Search).ToList();

就可以得到所有分词所得的token,另外TokenizerMode.Search参数使得Tokenize方法的结果中包含更全面的分词结果,比如“语言学家”会得到四个token,即“[语言, (0, 2)], [学家, (2, 4)], [语言学, (0, 3)], [语言学家, (0, 4)]”,这在创建索引和搜索时都很有帮助。

2、JiebaAnalyzer

Tokenizer类实现分词,而添加索引和搜索需要的是Analyzer,JiebaAnalyzer只要调用JiebaTokenizer即可。

public override TokenStream TokenStream(string fieldName, TextReader reader)
{
var seg = new JiebaSegmenter();
TokenStream result = new JiebaTokenizer(seg, reader);
// This filter is necessary, because the parser converts the queries to lower case.
result = new LowerCaseFilter(result);
result = new StopFilter(true, result, StopWords);
return result;
}

除了JiebaTokenizer,JiebaAnalyzer还会用到LowerCaseFilterStopFilter。前者可将索引和搜索的内容正则化,忽略大小写,后者则过滤掉停用词。这里使用的停用词列表合并了NLTK的英文停用词和哈工大的中文停用词。

3、创建索引和搜索

创建索引时,IndexWriter要使用JiebaAnalyzer的实例:

var analyzer = new JiebaAnalyzer();

using (var writer = new IndexWriter(Directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED))
{
// replaces older entry if any
foreach (var sd in data)
{
AddToLuceneIndex(sd, writer);
} analyzer.Close();
}

搜索的时候,先将用户的输入分词:

private static string GetKeyWordsSplitBySpace(string keywords, JiebaTokenizer tokenizer)
{
var result = new StringBuilder(); var words = tokenizer.Tokenize(keywords); foreach (var word in words)
{
if (string.IsNullOrWhiteSpace(word.Word))
{
continue;
} result.AppendFormat("{0} ", word.Word);
} return result.ToString().Trim();
}

比如如果用户输入的是“语言学家”,那么该函数的返回值是“语言 学家 语言学 语言学家”,为后面的搜索做好准备(另外,我们还可以为每个词加上一个*,这样只要部分匹配就可以搜到结果)。最后的搜索实现是:

private static IEnumerable<News> SearchQuery(string searchQuery, string searchField = "")
{
if (string.IsNullOrEmpty(searchQuery.Replace("*", "").Replace("?", "")))
{
return new List<News>();
} using (var searcher = new IndexSearcher(Directory, false))
{
var hitsLimit = ;
//var analyzer = new StandardAnalyzer(Version.LUCENE_30);
var analyzer = GetAnalyzer(); if (!string.IsNullOrEmpty(searchField))
{
var parser = new QueryParser(Version.LUCENE_30, searchField, analyzer);
var query = ParseQuery(searchQuery, parser);
var hits = searcher.Search(query, hitsLimit).ScoreDocs;
var results = MapLuceneToDataList(hits, searcher); analyzer.Dispose();
return results;
}
else
{
var parser = new MultiFieldQueryParser(Version.LUCENE_30, new[] { "Id", "Title", "Content" }, analyzer);
var query = ParseQuery(searchQuery, parser);
var hits = searcher.Search(query, null, hitsLimit, Sort.RELEVANCE).ScoreDocs;
var results = MapLuceneToDataList(hits, searcher); analyzer.Close();
return results;
}
}
}

这里的searchField参数可以指定特定字段进行搜索,如果为空,则对所有字段进行搜索。至此实现了最基本的集成。

JiebaTokenizer、JiebaAnalyzer的实现和示例代码都可在jiebaForLuceneNet找到。

4、Luke.Net

Luke.Net可以查看Lucene.Net生成的索引内容,这在开发和调试Lucene的时候会特别有帮助。

参考:

Lucene.Net ultra fast search for MVC or WebForms site

Lucene.Net – Custom Synonym Analyzer

https://github.com/JimLiu/Lucene.Net.Analysis.PanGu

http://pangusegment.codeplex.com/wikipage?title=PanGu4Lucene

http://luke.codeplex.com/releases/view/82033

【转】jieba.NET与Lucene.Net的集成的更多相关文章

  1. jieba.NET与Lucene.Net的集成

    首先声明:我对Lucene.Net并不熟悉,但搜索确实是分词的一个重要应用,所以这里还是尝试将两者集成起来,也许对你有一参考. 看到了两个中文分词与Lucene.Net的集成项目:Lucene.Net ...

  2. Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

  3. ]NET Core Lucene.net和PanGu分词实现全文检索

    Lucene.net和PanGu分词实现全文检索 Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考   前言:目前自己在做使用Lucene. ...

  4. spark mllib lda 简单示例

    舆情系统每日热词用到了lda主题聚类 原先的版本是python项目,分词应用Jieba,LDA应用Gensim 项目工作良好 有以下几点问题 1 舆情产品基于elasticsearch大数据,es内应 ...

  5. apache开源项目--PDFBox

    PDFBox是Java实现的PDF文档协作类库,提供PDF文档的创建.处理以及文档内容提取功能,也包含了一些命令行实用工具. 主要特性包括: 从PDF提取文本 合并PDF文档 PDF 文档加密与解密 ...

  6. (转)ElasticSearch学习

    (二期)21.全文搜索引擎Elasticsearch [课程21]elasticsearch.xmind82.1KB [课程21]lucene.xmind0.8MB [课程21]基本用法....api ...

  7. (转)mblog解读(二)

    (二期)12.开源博客项目mblog解读(二) [课程12]freema...模板.xmind77.9KB [课程12]hibernat...arch.xmind0.1MB freemarker模板技 ...

  8. 记一次结巴分词.net core 2.0版 nuget发布过程

    最近用到分词考虑很久,选用了结巴分词,原因见博客Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考 既然选好了,难就开始行动吧 . 查了.ne ...

  9. Java文件操作系列[1]——PDFBox实现分页提取PDF文本

    需求:用java分页提取PDF文本. PDFBox是一个很好的可以满足上述需求的开源工具. 1.PDF文档结构 要解析PDF文本,我们首先要了解PDF文件的结构. 关于PDF文档,最重要的几点: 一, ...

随机推荐

  1. 通过一个例子了解Ajax

    Ajax指的Asyncronous JavaScript and XML Ajax并不是什么新的编程语言, 它是现有一些东西的应用.从它的名称中就可以看出来 假如我们设想, 浏览器展示了一个页面,但需 ...

  2. jenkins 安装 + maven + git部署

    1. 安装JDK 2. 安装maven 3. 安装git 4. 安装tomcat tar zxvf apache-tomcat-8.5.14.tar.gz 找到tomcat-->config-- ...

  3. Cortex-M3基础

    (一)寄存器 1 寄存器组      R0-R12: 通用寄存器 ------------------------------------------------------------------- ...

  4. dp练习 2016.2.24

    很经典的一道状压dp(似乎叫做旅行商问题),用f[i][s]表示在到达点i,已经经过的城市用二进制表示为s,于是方程就很简单了: f[i][s] = min { f[j][s ^ (1 << ...

  5. C语言宏定义中的#和##的作用【转】

    本文转载自:http://my.oschina.net/shelllife/blog/123202 在宏定义中#和##的作用是:前者将宏定义的变量转化为字符串:后者将其前后的两个宏定义中的两个变量无缝 ...

  6. 我在linux中使用的vundle 和 vimrc配置

    set nocompatible filetype off set rtp+=~/.vim/bundle/vundle/ call vundle#rc() Plugin 'gmarik/vundle' ...

  7. 九数组分数|2015年蓝桥杯B组题解析第五题-fishers

    九数组分数 1,2,3...9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码. #include <stdio.h> void t ...

  8. 论文笔记——Data-free Parameter Pruning for Deep Neural Networks

    论文地址:https://arxiv.org/abs/1507.06149 1. 主要思想 权值矩阵对应的两列i,j,如果差异很小或者说没有差异的话,就把j列与i列上(合并,也就是去掉j列),然后在下 ...

  9. C++课程小结 继承与派生

    单继承与多重继承的区别 单继承:一个子类(派生类)只有一个父类(只由一个基类派生而成) 多继承:一个子类(派生类)有多个父类(由多个基类派生而成) 派生类的构成 (1) 从基类继承过来的成员(包括数据 ...

  10. Cocos2d-x学习笔记(五)调度

    在init方法中增加下边的代码,建议使用schedule函数,而不是scheduleUpdate函数,因为,后者默认是调用update函数,在如果有多个函数需要调度时,不是很灵活. auto labe ...