jieba.NET与Lucene.Net的集成
首先声明:我对Lucene.Net并不熟悉,但搜索确实是分词的一个重要应用,所以这里还是尝试将两者集成起来,也许对你有一参考。
看到了两个中文分词与Lucene.Net的集成项目:Lucene.Net.Analysis.PanGu和Lucene.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还会用到LowerCaseFilter和StopFilter。前者可将索引和搜索的内容正则化,忽略大小写,后者则过滤掉停用词。这里使用的停用词列表合并了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的集成的更多相关文章
- 【转】jieba.NET与Lucene.Net的集成
首先声明:我对Lucene.Net并不熟悉,但搜索确实是分词的一个重要应用,所以这里还是尝试将两者集成起来,也许对你有一参考. 看到了两个中文分词与Lucene.Net的集成项目:Lucene.Net ...
- Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考
前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...
- ]NET Core Lucene.net和PanGu分词实现全文检索
Lucene.net和PanGu分词实现全文检索 Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考 前言:目前自己在做使用Lucene. ...
- spark mllib lda 简单示例
舆情系统每日热词用到了lda主题聚类 原先的版本是python项目,分词应用Jieba,LDA应用Gensim 项目工作良好 有以下几点问题 1 舆情产品基于elasticsearch大数据,es内应 ...
- apache开源项目--PDFBox
PDFBox是Java实现的PDF文档协作类库,提供PDF文档的创建.处理以及文档内容提取功能,也包含了一些命令行实用工具. 主要特性包括: 从PDF提取文本 合并PDF文档 PDF 文档加密与解密 ...
- (转)ElasticSearch学习
(二期)21.全文搜索引擎Elasticsearch [课程21]elasticsearch.xmind82.1KB [课程21]lucene.xmind0.8MB [课程21]基本用法....api ...
- (转)mblog解读(二)
(二期)12.开源博客项目mblog解读(二) [课程12]freema...模板.xmind77.9KB [课程12]hibernat...arch.xmind0.1MB freemarker模板技 ...
- 记一次结巴分词.net core 2.0版 nuget发布过程
最近用到分词考虑很久,选用了结巴分词,原因见博客Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考 既然选好了,难就开始行动吧 . 查了.ne ...
- Java文件操作系列[1]——PDFBox实现分页提取PDF文本
需求:用java分页提取PDF文本. PDFBox是一个很好的可以满足上述需求的开源工具. 1.PDF文档结构 要解析PDF文本,我们首先要了解PDF文件的结构. 关于PDF文档,最重要的几点: 一, ...
随机推荐
- Oracle存储过程语法
原文链接:http://www.jb51.net/article/31805.htm Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 ...
- 转:学习笔记:delphi多线程学识
学习笔记:delphi多线程知识 最近一直在温习旧的知识,刚好学习了一下Java的线程安全方面的知识,今天想起之前一直做的Delphi开发,所以还是有必要温习一下,看看这些不同的编程语言有什么不同之处 ...
- The innocence is brilliant.
[11.20~12.20] 2016年的最后一个月在听Avril的歌,感觉她发音状态好好(对此建议去听<Wish You Were Here>!!!) 到此12月份的活都干完了吧~还剩最后 ...
- php 二位数组按某个键值排序
$arr=[ array( 'name'=>'小坏龙', 'age'=>28 ), array( 'name'=>'小坏龙2', 'age'=>14 ), array( 'na ...
- Linux内核笔记--深入理解文件描述符
内核版本:linux-2.6.11 文件描述符(file descriptor)在Linux编程里随处可见,设备读写.网络通信.进程通信,fd可谓是关键中的关键. 深入理解可以增加我们使用它的信心. ...
- 头显HTC Vive北美直降100美元,中国区降价活动今日公布
如果你现在想要购买一台VR头显,591ARVR资讯网www.591arvr.com的小编提醒大家可以等一等,在即将到来的年末促销中各种VR设备都将迎来大力度降价.目前北美市场的HTC Vive已经直降 ...
- MAC帧和IP数据报
- C# winfrom 窗体的StartPosition 属性
StartPosition属性有如下选项,分别含义如下: CenterParent 窗体在其父窗体中居中. CenterScreen 窗体在当前显示窗口中居中,其尺寸在窗体大小中指定. Manual ...
- python中非关键字可变长参数和关键字变量参数的区别
#非关键字可变长参数 def add(*arg): return type(arg) print add() #打印结果 <type 'tuple'> #关键字变量参数 def ab ...
- bat获取所有的参数
bat默认只能获取到1-9个参数,分别用%1 %2 ... %9引用,如果传给bat的参数大于9个,就必须用shift. 工作需要,要写个bat脚本,获取所有的参数,再将所有的参数传给Java,代码如 ...