zoukankan      html  css  js  c++  java
  • Lucene.net基本功能核心代码

    1. 基本应用


    using System;
    using System.Collections.Generic;
    using System.Text;
    using Lucene.Net;
    using Lucene.Net.Analysis;
    using Lucene.Net.Analysis.Standard;
    using Lucene.Net.Documents;
    using Lucene.Net.Index;
    using Lucene.Net.QueryParsers;
    using Lucene.Net.Search;
    using Lucene.Net.Store;
    using Lucene.Net.Util;

     

    namespace ConsoleApplication1.Lucene
    {
       public class LuceneTest
       {
         private const string FieldName = “name”;
         private const string FieldValue = “value”;

         private Directory directory = new RAMDirectory();
         private Analyzer analyzer = new StandardAnalyzer();

         public LuceneTest()
         {
         }

         private void Index()
         {
           IndexWriter writer = new IndexWriter(directory, analyzer, true);
           writer.maxFieldLength = 1000;
         
           for (int i = 1; i <= 100; i++)
           {
             Document document = new Document();

             document.Add(new Field(FieldName, “name” + i, Field.Store.YES, Field.Index.UN_TOKENIZED));
             document.Add(new Field(FieldValue, “Hello, World!”, Field.Store.YES, Field.Index.TOKENIZED));

             writer.AddDocument(document);
           }

           writer.Optimize();
           writer.Close();
         }

         private void Search()
         {
           Query query = QueryParser.Parse(“name*”, FieldName, analyzer);

           IndexSearcher searcher = new IndexSearcher(directory);

           Hits hits = searcher.Search(query);
         
           Console.WriteLine(“符合条件记录:{0}; 索引库记录总数:{1}”, hits.Length(), searcher.Reader.NumDocs());
           for (int i = 0; i < hits.Length(); i++)
           {
             int docId = hits.Id(i);
             string name = hits.Doc(i).Get(FieldName);
             string value = hits.Doc(i).Get(FieldValue);
             float score = hits.Score(i);

             Console.WriteLine(“{0}: DocId:{1}; Name:{2}; Value:{3}; Score:{4}”,
               i + 1, docId, name, value, score);
           }

           searcher.Close();
         }
       }
    }

    除了 RAMDirectory,还可以使用 FSDirectory。(注意 FSDirectory.GetDirectory 的 create 参数,为 true 时将删除已有索引库文件,可以通过 IndexReader.IndexExists() 方法判断。)

    从指定目录打开已有索引库。

    private Directory directory = FSDirectory.GetDirectory(“c:\index”, false);

    将索引库载入内存,以提高搜索速度。

    private Directory directory = new RAMDirectory(FSDirectory.GetDirectory(@”c:\index”, false));
    //或
    //private Directory directory = new RAMDirectory(c:\index”);

    2. 多字段搜索

    使用 MultiFieldQueryParser 可以指定多个搜索字段。

    Query query = MultiFieldQueryParser.Parse(“name*”, new string[] { FieldName, FieldValue }, analyzer);

     

    IndexReader reader = IndexReader.Open(directory);
    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);

    3. 多条件搜索

    除了使用 QueryParser.Parse 分解复杂的搜索语法外,还可以通过组合多个 Query 来达到目的。

    Query query1 = new TermQuery(new Term(FieldValue, “name1″)); // 词语搜索
    Query query2 = new WildcardQuery(new Term(FieldName, “name*”)); // 通配符
    //Query query3 = new PrefixQuery(new Term(FieldName, “name1″)); // 字段搜索 Field:Keyword,自动在结尾添加 *
    //Query query4 = new RangeQuery(new Term(FieldNumber, NumberTools.LongToString(11L)), new Term(FieldNumber, NumberTools.LongToString(13L)), true); // 范围搜索
    //Query query5 = new FilteredQuery(query, filter); // 带过滤条件的搜索
         
    BooleanQuery query = new BooleanQuery();
    query.Add(query1, BooleanClause.Occur.MUST);
    query.Add(query2, BooleanClause.Occur.MUST);

     

    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);

    4. 设置权重

    可以给 Document 和 Field 增加权重(Boost),使其在搜索结果排名更加靠前。缺省情况下,搜索结果以 Document.Score 作为排序依据,该数值越大排名越靠前。Boost 缺省值为 1。

    Score = Score * Boost

    通过上面的公式,我们就可以设置不同的权重来影响排名。

    如下面的例子中根据 VIP 级别设定不同的权重。

    Document document = new Document();
    switch (vip)
    {
       case VIP.Gold: document.SetBoost(2F); break;
       case VIP.Argentine: document.SetBoost(1.5F); break;
    }

    只要 Boost 足够大,那么就可以让某个命中结果永远排第一位,这就是百度等网站的”收费排名”业务。明显有失公平,鄙视一把。

    5. 排序

    通过 SortField 的构造参数,我们可以设置排序字段,排序条件,以及倒排。

    Sort sort = new Sort(new SortField(FieldName, SortField.DOC, false));

     

    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query, sort);

    排序对搜索速度影响还是很大的,尽可能不要使用多个排序条件。

    6. 过滤

    使用 Filter 对搜索结果进行过滤,可以获得更小范围内更精确的结果。

    举个例子,我们搜索上架时间在 2005-10-1 到 2005-10-30 之间的商品。
    对于日期时间,我们需要转换一下才能添加到索引库,同时还必须是索引字段。

    // index
    document.Add(FieldDate, DateField.DateToString(date), Field.Store.YES, Field.Index.UN_TOKENIZED);

     

    //…

    // search
    Filter filter = new DateFilter(FieldDate, DateTime.Parse(“2005-10-1″), DateTime.Parse(“2005-10-30″));
    Hits hits = searcher.Search(query, filter);

    除了日期时间,还可以使用整数。比如搜索价格在 100 ~ 200 之间的商品。
    Lucene.Net NumberTools 对于数字进行了补位处理,如果需要使用浮点数可以自己参考源码进行。

    // index
    document.Add(new Field(FieldNumber, NumberTools.LongToString((long)price), Field.Store.YES, Field.Index.UN_TOKENIZED));

     

    //…

    // search
    Filter filter = new RangeFilter(FieldNumber, NumberTools.LongToString(100L), NumberTools.LongToString(200L), true, true);
    Hits hits = searcher.Search(query, filter);

    使用 Query 作为过滤条件。

    QueryFilter filter = new QueryFilter(QueryParser.Parse(“name2″, FieldValue, analyzer));

    我们还可以使用 FilteredQuery 进行多条件过滤。

    Filter filter = new DateFilter(FieldDate, DateTime.Parse(“2005-10-10″), DateTime.Parse(“2005-10-15″));
    Filter filter2 = new RangeFilter(FieldNumber, NumberTools.LongToString(11L), NumberTools.LongToString(13L), true, true);

     

    Query query = QueryParser.Parse(“name*”, FieldName, analyzer);
    query = new FilteredQuery(query, filter);
    query = new FilteredQuery(query, filter2);

    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);

    7. 分布搜索

    我们可以使用 MultiReader 或 MultiSearcher 搜索多个索引库。

    MultiReader reader = new MultiReader(new IndexReader[] { IndexReader.Open(@”c:\index”), IndexReader.Open(@”\\server\index”) });
    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);

    IndexSearcher searcher1 = new IndexSearcher(reader1);
    IndexSearcher searcher2 = new IndexSearcher(reader2);
    MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
    Hits hits = searcher.Search(query);

    还可以使用 ParallelMultiSearcher 进行多线程并行搜索。

    8. 合并索引库

    将 directory1 合并到 directory2 中。

    Directory directory1 = FSDirectory.GetDirectory(“index1″, false);
    Directory directory2 = FSDirectory.GetDirectory(“index2″, false);

     

    IndexWriter writer = new IndexWriter(directory2, analyzer, false);
    writer.AddIndexes(new Directory[] { directory });
    Console.WriteLine(writer.DocCount());
    writer.Close();

    9. 显示搜索语法字符串

    我们组合了很多种搜索条件,或许想看看与其对等的搜索语法串是什么样的。

    BooleanQuery query = new BooleanQuery();
    query.Add(query1, true, false);
    query.Add(query2, true, false);
    //…

     

    Console.WriteLine(“Syntax: {0}”, query.ToString());

    输出:
    Syntax: +(name:name* value:name*) +number:[0000000000000000b TO 0000000000000000d]

    呵呵,就这么简单。

    10. 操作索引库

    删除 (软删除,仅添加了删除标记。调用 IndexWriter.Optimize() 后真正删除。)

    IndexReader reader = IndexReader.Open(directory);

     

    // 删除指定序号(DocId)的 Document。
    reader.Delete(123);

    // 删除包含指定 Term 的 Document。
    reader.Delete(new Term(FieldValue, “Hello”));

    // 恢复软删除。
    reader.UndeleteAll();

    reader.Close();

    增量更新 (只需将 create 参数设为 false,即可往现有索引库添加新数据。)

    Directory directory = FSDirectory.GetDirectory(“index”, false);
    IndexWriter writer = new IndexWriter(directory, analyzer, false);
    writer.AddDocument(doc1);
    writer.AddDocument(doc2);
    writer.Optimize();
    writer.Close();

    11. 优化

    批量向 FSDirectory 增加索引时,增大合并因子(mergeFactor )和最小文档合并数(minMergeDocs)有助于提高性能,减少索引时间。

    IndexWriter writer = new IndexWriter(directory, analyzer, true);

     

    writer.maxFieldLength = 1000; // 字段最大长度
    writer.mergeFactor = 1000;
    writer.minMergeDocs = 1000;

    for (int i = 0; i < 10000; i++)
    {
       // Add Documentes…
    }

    writer.Optimize();
    writer.Close();

    ---恢复内容结束---

  • 相关阅读:
    Meten Special Activities II
    Meten Special Activities II
    Meten Special Activities II
    Meten Special Activities II
    Meten Special Activities
    Meten Special Activities
    Meten Special Activities
    Meten Special Activities
    Meten Special Activities
    冒泡排序和选择排序
  • 原文地址:https://www.cnblogs.com/servant/p/3030119.html
Copyright © 2011-2022 走看看