zoukankan      html  css  js  c++  java
  • Lucene.Net实现GroupBy的效果(2.3.1版)

    本文简单介绍Lucene.Net实现GroupBy效果的方法,与《Lucene.Net 按类别统计搜索结果数 》一文类似。注意,这种使用方法很影响效率,特别是命中结果多的情况下。这段代码修正自2.3.1版本,其它版本可能会与此有差别。

    改造方法仍然是修改IndexSearcher,这里不再修改类库,而是通过自己的代码来实现。

    扩充IndexSearcher类
    实现与 HitQueue类完全一致,只因为这里无法使用类库提供的构造函数
        /// <summary>
        
    /// 增加新的TopDocCollector类,无法直接继承TopDocCollector
        
    /// </summary>
        public class TopDocCollectorExtension : HitCollector
        {
            
    private ScoreDoc reusableSD;

            
    internal int totalHits;
            
    internal PriorityQueue hq;

            
    /// <summary>Construct to collect a given number of hits.</summary>
            
    /// <param name="numHits">the maximum number of hits to collect
            
    /// </param>
            public TopDocCollectorExtension(int numHits)
                : 
    this(numHits, new HitQueueExtension(numHits))
            {
            }
            
    /// <summary>
            
    /// 注入IndexSearcherExtension对象
            
    /// </summary>
            private IndexSearcherExtension searcher;
            
    /// <summary>
            
    /// 构造函数注入对象
            
    /// </summary>
            
    /// <param name="numHits"></param>
            
    /// <param name="searcher"></param>
            public TopDocCollectorExtension(int numHits, IndexSearcherExtension searcher)
                : 
    this(numHits)
            {
                
    this.searcher = searcher;
            }

            
    internal TopDocCollectorExtension(int numHits, PriorityQueue hq)
            {
                
    this.hq = hq;
            }

            
    /// <summary>
            
    /// 临时数据,用于排重
            
    /// </summary>
            private Dictionary<intint> dict = new Dictionary<intint>();
            
    // 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();
                        
    string value1 = string.Empty;
                        
    string value2 = string.Empty;
                        
    int len = value.Length;
                        
    int len1 = (int)Math.Ceiling(len / 2.0f);
                        
    int len2 = len - len1;
                        
    int hash1 = value.Substring(0, len1).GetHashCode();
                        
    int hash2 = value.Substring(len1, len2).GetHashCode();
                        
    if (!(dict.ContainsKey(hash1) && dict.ContainsValue(hash2)))
                            dict.Add(hash1, hash2);
                        
    else
                            
    return;
                    }

                    totalHits
    ++;
                    
    if (reusableSD == null)
                    {
                        reusableSD 
    = new ScoreDoc(doc, score);
                    }
                    
    else if (score >= reusableSD.score)
                    {
                        
    // reusableSD holds the last "rejected" entry, so, if
                        
    // this new score is not better than that, there's no
                        
    // need to try inserting it
                        reusableSD.doc = doc;
                        reusableSD.score 
    = score;
                    }
                    
    else
                    {
                        
    return;
                    }
                    reusableSD 
    = (ScoreDoc)hq.InsertWithOverflow(reusableSD);
                }
            }

            
    /// <summary>The total number of documents that matched this query. </summary>
            public virtual int GetTotalHits()
            {
                
    return totalHits;
            }

            
    /// <summary>The top-scoring hits. </summary>
            public virtual TopDocs TopDocs()
            {
                ScoreDoc[] scoreDocs 
    = new ScoreDoc[hq.Size()];
                
    for (int i = hq.Size() - 1; i >= 0; i--)
                    
    // put docs in array
                    scoreDocs[i] = (ScoreDoc)hq.Pop();

                
    float maxScore = (totalHits == 0? System.Single.NegativeInfinity : scoreDocs[0].score;

                
    return new TopDocs(totalHits, scoreDocs, maxScore);
            }
        }
    OK生产者完成了,下面看看消费者怎么搞。
            static void Main(string[] args)
            {
                IndexWriter writer 
    = new IndexWriter("e:\\index"new StandardAnalyzer(), true);
                Document doc 
    = new Document();
                doc.Add(
    new Field("field""query value!", Field.Store.YES, Field.Index.TOKENIZED));
                writer.AddDocument(doc);
                writer.AddDocument(doc);
                writer.AddDocument(doc);
                writer.Close();

                IndexSearcherExtension searcher 
    = new IndexSearcherExtension("e:\\index");
                searcher.GroupBy(
    "field");
                Query q 
    = new QueryParser("field"new StandardAnalyzer())
                    .Parse(
    "query");
                Hits docs 
    = searcher.Search(q);
                
    for (int i = 0; i < docs.Length(); i++)
                {
                    Console.WriteLine(docs.Doc(i).Get(
    "field"));
                }
                searcher.Close();

                Console.ReadKey();
            }
    添加了三个相同的文档,结果只查询到一个结果,从而达到了目的。这段修改比较简单,应该还可以设计出更加高效的算法。好长时间没写博客有些生疏了~~!
  • 相关阅读:
    Dojo初探之5:dojo的request(请求)操作、请求过程事件绑定和隐藏数据data()操作(基于dojo1.11.2版本)
    Dojo初探之4:dojo的event(鼠标/键盘)事件绑定操作(基于dojo1.11.2版本)
    为什么使用dojo?dojo与jquery有什么不同?dojo适合什么开发场景?
    Dojo初探之3:dojo的DOM操作、query操作和domConstruct元素位置操作(基于dojo1.11.2版本)
    nodejs实战:使用原生nodeJs模块实现静态文件及REST请求解析及响应(基于nodejs6.2.0版本,不使用express等webMVC框架 )
    Dojo初探之2:设置dojoConfig详解,dojoConfig参数详解+Dojo中预置自定义AMD模块的四种方式(基于dojo1.11.2)
    Dojo初探之1:AMD规范,编写符合AMD规范(异步模块加载机制)的模块化JS(其中dojo采用1.11.2版本)
    POI使用:用poi接口不区分xls/xlsx格式解析Excel文档(41种日期格式解析方法,5种公式结果类型解析方法,3种常用数值类型精度控制办法)
    Lucene全文搜索之分词器:使用IK Analyzer中文分词器(修改IK Analyzer源码使其支持lucene5.5.x)
    搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)
  • 原文地址:https://www.cnblogs.com/birdshover/p/1533368.html
Copyright © 2011-2022 走看看