`

[Lucene.Net] 基本用法

阅读更多

本文仅记录一些简单的使用方法,供初学者参考。
以下例子采用 Lucene.NET 1.9 版本,可取去 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() 方法判断。)

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

 

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->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. 多条件搜索

 

 

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();

 

相关参数说明


转自《深入 Lucene 索引机制

利用 Lucene,在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率。当你需要索引大量的文件时,你会注意到索引过程的瓶颈是在往磁盘上写索引文件的过程中。为了解决这个问题, Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢?幸运的是,Lucene 的类 IndexWriter 提供了三个参数用来调整缓冲区的大小以及往磁盘上写索引文件的频率。

1.合并因子 (mergeFactor)

这个参数决定了在 Lucene 的一个索引块中可以存放多少文档以及把磁盘上的索引块合并成一个大的索引块的频率。比如,如果合并因子的值是 10,那么当内存中的文档数达到 10 的时候所有的文档都必须写到磁盘上的一个新的索引块中。并且,如果磁盘上的索引块的隔数达到 10 的话,这 10 个索引块会被合并成一个新的索引块。这个参数的默认值是 10,如果需要索引的文档数非常多的话这个值将是非常不合适的。对批处理的索引来讲,为这个参数赋一个比较大的值会得到比较好的索引效果。

2.最小合并文档数 (minMergeDocs)

这个参数也会影响索引的性能。它决定了内存中的文档数至少达到多少才能将它们写回磁盘。这个参数的默认值是10,如果你有足够的内存,那么将这个值尽量设的比较大一些将会显著的提高索引性能。

3.最大合并文档数 (maxMergeDocs)

这个参数决定了一个索引块中的最大的文档数。它的默认值是 Integer.MAX_VALUE,将这个参数设置为比较大的值可以提高索引效率和检索速度,由于该参数的默认值是整型的最大值,所以我们一般不需要改动这个参数。


-------------------迷糊中的分割线-----------------------------

Lucene 相关资源:

1. Lucene 官方网站
2. Apache Lucene
3. Lucene FAQ
4. Lucene.Net
5. Lucene API (Java)
6. DotLucene
7. Luke - Lucene Index Toolbox
8. Nutch
9. LUCENE.COM.CN 中国
10. Compass
11. 实战 Lucene,第 1 部分: 初识 Lucene
12. 深入 Lucene 索引机制

 

转至:http://www.rainsts.net/article.asp?id=313

分享到:
评论

相关推荐

    Lucene.Net基本用法

    ### Lucene.Net基本用法详解 #### 一、概述 Lucene.Net是.NET平台上的一款高性能全文搜索引擎库,基于Java版的Lucene开发而来。它提供了强大的文本搜索功能,支持复杂查询,广泛应用于文档检索、网站搜索等场景。...

    lucene.NET 中文分词

    - **缓存策略**:合理使用Lucene.NET的缓存机制,如TermVector缓存,可以提升查询性能。 总的来说,Lucene.NET在中文分词和高亮显示方面的应用需要结合合适的分词器,并进行适当的配置和优化。开发者可以根据实际...

    Lucene.Net

    示例代码可以帮助快速上手,而功能文档则详细解释了各种API的使用方法和最佳实践。 **应用场景:** Lucene.Net广泛应用于信息检索系统、内容管理系统、电子商务网站、论坛、博客平台等需要全文搜索功能的项目。通过...

    lucene.net 2.9.1 源码

    《深入剖析Lucene.NET 2.9.1:源码解析与应用开发》 Lucene.NET 2.9.1是开源搜索引擎库Lucene的.NET版本,它为.NET开发者提供了强大的全文检索和索引功能。这个版本的源码提供了一个宝贵的资源,帮助我们理解其内部...

    Lucene.Net2.3源码,最新版

    这些是 HTML 文档,可能包含了 Lucene.Net 的概述和组件介绍,帮助用户了解库的功能和使用方法。NDoc(.NET 文档生成器)可能被用来自动生成这些文档,从注释和源代码中提取信息。 9. **Lucene.Net-2.3.1.ndoc** ...

    lucene.net 2.9.2 实现索引生成,修改,查询,删除实例

    在Lucene.NET中,我们可以使用`IndexWriter`的`DeleteDocuments`方法来删除文档,然后再次添加。 ```csharp // 删除匹配特定条件的文档 indexWriter.DeleteDocuments(new TermQuery(new Term("id", "document_id"))...

    lucene.net基本应用(doc)

    这个示例代码展示了如何在 .NET 环境下使用 Lucene.NET 进行基本的索引创建和查询操作。 1. **索引创建**: - `IndexWriter` 类是用于创建、更新和优化 Lucene 索引的主要类。在示例中,`new IndexWriter...

    Lucene.Net.rar 2.0 ver asp.net 组件

    下面我们将深入探讨Lucene.Net 2.0的主要特性和使用方法。 **1. 全文搜索功能** Lucene.Net的核心就是强大的全文检索能力。它能够对文本进行分词,并建立索引,从而实现快速的关键词查找。在ASP.NET应用中,这使得...

    lucene.net完整源码

    在实际应用中,利用Lucene.NET进行基本操作主要包括以下步骤: 1. 创建索引:首先,我们需要创建一个IndexWriter实例,然后通过AddDocument方法将要索引的文档添加到索引中。 2. 搜索索引:使用Analyzer进行分词,...

    Lucene.Net 2.0 源码+文档

    《深入理解Lucene.Net 2.0:源码与文档解析》 Lucene.Net是一个开源的全文搜索引擎库,它是Apache Lucene项目在.NET平台上的实现,由DotLucene发展而来,广泛应用于各种信息检索和文本挖掘场景。这个资料包包含了...

    Lucene.Net-search

    通过这个示例项目,开发者可以学习到 Lucene.Net 在实际项目中的应用方法,理解如何将搜索引擎集成到 Web 应用中,提高搜索性能。 总之,Lucene.Net 是一个强大的全文搜索引擎,能有效提升 MVC 和 WebForms 网站的...

    lucene.net源代码

    《深入剖析Lucene.NET:基于源代码的实例解析》 Lucene.NET,作为Apache Lucene的.NET版本,是一个高性能、全文检索库,为.NET开发者提供了强大的文本搜索功能。本实例将带您深入理解Lucene.NET的内部机制,通过源...

    lucene.net实例

    在 Lucene.NET 中,可以使用 Term(代表一个唯一的文档标识)或者 Query(代表一组文档)作为参数调用 IndexWriter 的 DeleteDocuments 方法来实现。删除操作会标记相应的文档为删除状态,实际清理工作会在下一次 ...

    autoSearch 基于Lucene.Net的站内搜索

    Lucene.Net使用TF-IDF(词频-逆文档频率)算法来计算文档的相关性。 在使用Lucene.Net进行站内搜索时,你需要遵循以下步骤: 1. **设置项目和引用**:首先,在你的C#项目中添加对Lucene.Net库的引用。你可以通过...

    Lucene.Net-2.9.2 c#源码

    4. 文档(Document):文档是Lucene.Net中的基本数据结构,用于存储索引的信息。每个字段(Field)代表文档的一部分,如标题、内容等。 5. 索引(Index):索引是Lucene.Net的核心,它将文档转换为倒排索引,使得...

    Lucene.net2.9.2源码

    Lucene.net是我从https://svn.apache.org/repos/asf/incubator/lucene.net/tags/Lucene.Net_2_9_2/ 上下载下来的,如果你想自己下载可以按照http://apps.hi.baidu.com/share/detail/22856972上面说的方法来下载。...

    lucene.net 2.0.4

    在本文中,我们将深入探讨Lucene.NET 2.0.4的主要特性和用法,以及如何利用它来优化您的应用程序的搜索体验。 一、核心概念与组件 1. 文档(Documents):在Lucene.NET中,文档是信息的基本单位,可以包含多个字段...

    Lucene.net建立索引,检索分页Demo

    在 Lucene.net 中,首先需要创建一个 IndexWriter 对象,然后使用 AddDocument 方法添加文档。每个文档由字段(Field)组成,字段可以设置不同的属性,如是否存储原始内容、是否可被搜索等。索引创建完成后,使用 ...

    Lucene.NET2.9搜索引擎源代码(C#)

    - **阅读文档**:先从官方文档和 README 开始,了解项目背景和基本使用方法。 - **分析源码**:逐个模块阅读源代码,理解类和方法的作用。 - **实践编程**:动手编写简单的搜索应用,结合源代码调试,加深理解。 - *...

    Lucene.Net2.9 Library

    - **SupportClass.cs**:包含了辅助类,这些类可能用于支持Lucene.Net的主要功能,如数据结构或工具方法。 - **AssemblyInfo.cs**:.NET项目的元数据文件,包含版本信息、版权信息等。 - **LucenePackage.cs**:可能...

Global site tag (gtag.js) - Google Analytics