• 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();
            }
    添加了三个相同的文档,结果只查询到一个结果,从而达到了目的。这段修改比较简单,应该还可以设计出更加高效的算法。好长时间没写博客有些生疏了~~!
  • 相关阅读:
    Go grpc 基本使用
    线程之间的数据库隔离方案
    mysql创建用户并设置所有权限
    Mysql InnoDB 共享表空间和独立表空间
    DB2错误码信息
    PhotoshopManager(缩放图片file---->byte[])
    SaveManager+DownloadManager(下载img,voice以及保存)
    ViewPager
    RegistereManager
    ServiceManager
  • 原文地址:https://www.cnblogs.com/birdshover/p/1533368.html
Copyright © 2020-2023  润新知