Lucene.Net 实现groupby并可以加入自定义过滤功能
来源:互联网 发布:js 获取数组长度 编辑:程序博客网 时间:2024/06/05 06:50
背景:在一个项目中搜索产品库,需要同一公司只显示一个产品的过滤功能.由于为了性能项目已经采用lucene.Net全文搜索架构,因此要"同一公司一个产品"的过滤功能就只能在lucene搜索上下功夫了.
本文是在Lucene.Net 2.9.2的源码里改的,下面开始通过源码来介绍,
一 首先修改IndexSearcher.cs文件,在此文件中增加 groupby排序的字段属性"FieldName",同时增加给此字段赋值的方法 GroupBy(string FieldName),注意应用时,在调用Search方法之前先调用GroupBy方法.
IndexSearcher.cs添加如下代码
/// <summary>
/// 增加GroupBy字段
/// </summary>
private string fieldName;
/// <summary>
/// 给TopDocCollector类的Collect方法使用。
/// </summary>
public string FieldName
{
get { return fieldName; }
}
/// <summary>
/// 在调用Search方法前一定要调用该方法。
/// </summary>
/// <param name="fieldName"></param>
public void GroupBy(string fieldName)
{
this.fieldName = fieldName;
}
二 TopFieldDocCollector.cs 该类的新增一个TopFieldDocCollector初始化方法,在新方法的增加IndexSearcher,
然后修改Collect方法,下面开始是排序效果的关键了
先定义一个泛型,用于保存groupby字段的值,在collect方法中去判断值有没有存在dict ,如果存在则跳转到下一条.
/// <summary>
/// 注入IndexSearcherExtension对象
/// </summary>
private IndexSearcher searcher;
/// <summary>
/// 构造函数注入对象
/// </summary>
/// <param name="numHits"></param>
/// <param name="searcher"></param>
public TopFieldDocCollector(IndexReader reader, Sort sort, int numHits,IndexSearcher searcher)
: base(new FieldSortedHitQueue(reader, sort.fields, numHits))
{
this.searcher = searcher;
}
/// <summary>
/// 临时数据,用于排重
/// </summary>
private Dictionary<int, int> dict = new Dictionary<int, int>();
/// <summary>
/// 临时数据,用于排重
/// </summary>
private Dictionary<int, int> dict = new Dictionary<int, int>();
// javadoc inherited
public override void Collect(int doc, float score)
{
if (score > 0.0f)
{
//排重算法
if (!string.IsNullOrEmpty(searcher.FieldName))
{
IndexReader reader = searcher.GetIndexReader();
Document docment = reader.Document(doc);
string value = docment.Get(searcher.FieldName).Trim();
if (!dict.ContainsKey(int.Parse(value)))
{
dict.Add(int.Parse(value), int.Parse(value));
}
else
{
return;
}
}
totalHits++;
if (reusableFD == null)
reusableFD = new FieldDoc(doc, score);
else
{
// Whereas TopScoreDocCollector can skip this if the
// score is not competitive, we cannot because the
// comparators in the FieldSortedHitQueue.lessThan
// aren't in general congruent with "higher score
// wins"
reusableFD.score = score;
reusableFD.doc = doc;
}
reusableFD = (FieldDoc) hq.InsertWithOverflow(reusableFD);
}
}
三 修改IndexSearcher.cs中将原来调用TopFieldDocCollector(IndexReader reader, Sort sort, int numHits)初始化的方法改为
新方法 (IndexReader reader, Sort sort, int numHits,IndexSearcher searcher)
四 测试
static void Main(string[] args) { Lucene.Net.Analysis.Analyzer analyzer = null; analyzer = new PanGuAnalyzer(); //这里用了盘古分词的方法 PanGu.Segment.Init(@"E:\工作\LED\Project\demo\Lucene.Net_2_9\Lucene.Net_2_9_2\PanGu.xml"); IndexWriter writer = new IndexWriter("e:\\index", analyzer, true); Document doc = new Document(); doc.Add(new Field("pro_Name", "LED节能灯", Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field("pro_Mem_ID", "61", Field.Store.YES, Field.Index.NO)); doc.Add(new Field("pro_Attr", ",61:12,13:led,14:129,", Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field("pro_price", "100", Field.Store.YES, Field.Index.UN_TOKENIZED)); Document doc2 = new Document(); doc2.Add(new Field("pro_Name", "LED日光灯", Field.Store.YES, Field.Index.ANALYZED)); doc2.Add(new Field("pro_Mem_ID", "62", Field.Store.YES, Field.Index.NO)); doc2.Add(new Field("pro_Attr", ",61:12,13:led,14:128,", Field.Store.YES, Field.Index.ANALYZED)); doc2.Add(new Field("pro_price", "200", Field.Store.YES, Field.Index.UN_TOKENIZED)); Document doc3 = new Document(); doc3.Add(new Field("pro_Name", "LED灯", Field.Store.YES, Field.Index.ANALYZED)); doc3.Add(new Field("pro_Mem_ID", "63", Field.Store.YES, Field.Index.NO)); doc3.Add(new Field("pro_Attr", ",61:12,", Field.Store.YES, Field.Index.ANALYZED)); doc3.Add(new Field("pro_price", "220", Field.Store.YES, Field.Index.UN_TOKENIZED)); writer.AddDocument(doc); writer.AddDocument(doc2); writer.AddDocument(doc3); writer.Close(); IndexSearcher searcher = new IndexSearcher("e:\\index"); BooleanQuery boolQuery = new BooleanQuery(); string queryString = "LED"; if (queryString != null && queryString != string.Empty && queryString != "") { boolQuery.Add(MultiFieldQueryParser.Parse(new string[] { queryString }, new string[] { "pro_Name" }, analyzer), BooleanClause.Occur.SHOULD); } searcher.GroupBy("pro_Mem_ID"); Sort sort = new Sort(); SortField f2 = new SortField("pro_price", SortField.FLOAT, false); sort.SetSort(new SortField[]{f2}); Hits docs = searcher.Search(boolQuery,null, sort); for (int i = 0; i < docs.Length(); i++) { Console.WriteLine(docs.Doc(i).Get("pro_Name") + "---" + docs.Doc(i).Get("pro_Mem_ID") + "--" + docs.Doc(i).Get("pro_Attr")); } searcher.Close(); Console.ReadKey(); }
五 小结 关键在于TopFieldDocCollector.cs中的collect方法,在这个方法中大家也以可加入自定义过滤规则,规则的参数可以通过IndexSearch类中初始化.
- Lucene.Net 实现groupby并可以加入自定义过滤功能
- Lucene 如何实现高性能 GroupBy <一>
- Lucene 如何实现高性能 GroupBy <二>
- lucene .NET 搜索图片 功能实现
- Lucene.net常见功能实现知识汇总
- 使用Lucene.NET实现数据检索功能
- Lucene.net实现自定义排序笔记
- atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php
- 使用Python的groupby实现压缩功能
- Java实现GroupBy/分组TopN功能
- 利用 Lucene 实现高级搜索功能并创建web应用程序
- android 自定义gallerey并实现预览功能
- lucene的开发环境配置,并实现lucene功能一:创建索引;及代码示例
- 如何实现asp.net中FileUpload文件类型过滤功能
- 如何实现asp.net中FileUpload文件类型过滤功能 .
- 如何实现asp.net中FileUpload文件类型过滤功能
- 实现图片过滤功能
- Lucene.net简单实现
- servlet3.0 资料收集
- 软件列表
- JDBC总结
- 你是否在开发正确的产品?
- 菜鸟带你秒杀单片机之51单片机篇—定时器
- Lucene.Net 实现groupby并可以加入自定义过滤功能
- 从程序上传数据到服务器文件中
- 【组建机器人技术民间爱好小组】
- linux下解压命令大全和 rpm命令使用简介
- http://beyondcow.com/code/
- Sql常用语句
- 学习C++应该精通的9本经典书籍
- 多线程操作stl::map引起的数据不一致问题的解决过程与方法
- 将MFC的CString 类型转化为C++标准数据类型std::string