`
poson
  • 浏览: 361503 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Lucene基本知识

阅读更多

 

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

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

 

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(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="11" unitname="l">11L</chmetcnv>)), new Term(FieldNumber, NumberTools.LongToString(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="13" unitname="l">13L</chmetcnv>)), 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(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2" unitname="F">2F</chmetcnv>); break;
case VIP.Argentine: document.SetBoost(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1.5" unitname="F">1.5F</chmetcnv>); 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 对搜索结果进行过滤,可以获得更小范围内更精确的结果。

举个例子,我们搜索上架时间在 <chsdate w:st="on" isrocdate="False" islunardate="False" day="1" month="10" year="2005">2005-10-1</chsdate> <chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="10" year="2005">2005-10-30</chsdate>之间的商品。
对于日期时间,我们需要转换一下才能添加到索引库,同时还必须是索引字段。

 

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

//...

// search
Filter filter = new DateFilter(FieldDate, DateTime.Parse("<chsdate w:st="on" isrocdate="False" islunardate="False" day="1" month="10" year="2005">2005-10-1</chsdate>"), DateTime.Parse("<chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="10" year="2005">2005-10-30</chsdate>"));
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(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="100" unitname="l">100L</chmetcnv>), NumberTools.LongToString(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="200" unitname="l">200L</chmetcnv>), 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("<chsdate w:st="on" isrocdate="False" islunardate="False" day="10" month="10" year="2005">2005-10-10</chsdate>"), DateTime.Parse("<chsdate w:st="on" isrocdate="False" islunardate="False" day="15" month="10" year="2005">2005-10-15</chsdate>"));
Filter filter2 = new RangeFilter(FieldNumber, NumberTools.LongToString(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="11" unitname="l">11L</chmetcnv>), NumberTools.LongToString(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="13" unitname="l">13L</chmetcnv>), 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,将这个参数设置为比较大的值可以提高索引效率和检索速度,由于该参数的默认值是整型的最大值,所以我们一般不需要改动这个参数。

 

当把文件最大的合并次数设置太大,内存可能不够用。

 

 

4、当把lucene作为实时的增量索引的时候。每次增加数据后,把搜索对象重新生成一次,增加的数据才能马上查询到。不知道有什么其他方法可以更快的查询到。

分享到:
评论

相关推荐

    lucene基本包

    这个“lucene基本包”包含了Lucene的核心组件,是理解和使用Lucene进行信息检索的基础。 1. **全文检索引擎架构** Lucene的核心理念是建立索引,以便快速查找文档中的信息。它通过将文本数据转换成便于搜索的结构...

    Lucene.Net基本用法

    通过实践这些知识点,开发者能够快速掌握Lucene.Net的核心功能,为构建高效全文搜索系统打下坚实基础。在未来的学习与项目中,不断探索Lucene.Net的更多可能性,将有助于提升搜索系统的性能与用户体验。

    lucene 3.4基本应用

    **Lucene 3.4 基本应用详解** Lucene 是一个开源的全文搜索引擎库,由Apache软件基金会开发并维护。它提供了高效、可扩展的搜索功能,被广泛应用于各种信息检索系统。本篇文章将深入探讨Lucene 3.4版本的基础应用,...

    lucene API最基本应用

    通过这些基础知识,你可以开始构建自己的全文搜索引擎或在现有项目中集成 Lucene 的功能。随着对 Lucene 更深入的理解,你会发现它提供了许多高级特性,如布尔查询、近似搜索、多字段搜索等,以满足更复杂的搜索需求...

    Lucene资料大全(包括Lucene_in_Action书等)

    这份PPT可能包含对Lucene基础知识的快速概览,如Lucene的主要特点、基本用法,以及适合初学者的示例代码。它可能以简洁易懂的方式解释Lucene的关键概念,对于快速入门Lucene是非常有价值的资源。 总的来说,这个...

    lucene3源码分析

    ### Lucene3源码分析知识点概述 #### 一、全文检索的基本原理 ##### 1. 总论 全文检索系统是一种高效的信息检索技术,能够帮助用户在海量文档中快速找到包含特定关键词的信息。Lucene是Java领域内最受欢迎的全文...

    lucene in action源码

    通过深入研究《Lucene in Action》的源码,开发者不仅可以理解Lucene的基本工作原理,还能学习如何实际应用这些知识,解决具体的搜索问题。对于初学者而言,这是一个很好的起点,可以帮助他们快速上手并逐步掌握全文...

    lucene in action英文版 lucene 3.30包

    "lucene in action.pdf" 是《Lucene in Action》的电子版,提供理论知识和实践经验的学习资料;"Lucene的- 3.0.3.zip.ZIP"可能是Lucene 3.0.3版本的源码或二进制包,可供开发者下载研究和使用。 总之,Lucene是一...

    Lucene3.5源码jar包

    以下是对这个版本中一些关键知识点的详细说明: 1. **索引结构**:Lucene的核心在于其高效的倒排索引结构。在源码中,你可以看到`IndexWriter`类如何处理文档的添加、删除和更新,以及`SegmentMerger`如何合并多个...

    Lucene In Action 第二版 高清中文版+附书源代码

    1. **Lucene基础知识**:介绍Lucene的基本概念,如文档、字段、术语、倒排索引和查询解析,以及如何创建一个基本的Lucene应用。 2. **索引构建**:涵盖如何将结构化和非结构化数据转化为可搜索的索引,包括分词器的...

    lucene

    在Java编程语言中,Lucene被广泛应用于各种需要全文搜索功能的系统,如网站、文档管理、知识库等。其强大的搜索性能和灵活的配置使得开发者能够快速构建自己的搜索引擎。 一、Lucene的基本架构 Lucene的核心架构...

    自己写的一个lucene知识点集合

    1. **Lucene 的基本概念** - **索引**:Lucene 首先将文档内容转化为倒排索引结构,便于快速查找匹配的文档。 - **字段**:每个文档可以包含多个字段,如标题、正文等,不同字段可以设置不同的分析器和存储方式。 ...

    Lucene全文检索引擎

    如果你对Lucene感兴趣,可以参考官方文档、教程和社区资源,例如Apache Lucene的官方网站,以及你提到的博客链接(https://1151461406.iteye.com/blog/2388343),这个链接可能包含了一些实战案例和进阶知识。...

    lucene in action 2nd edition, lucene in action 第二版 PDF

    6. **实战案例**:提供了丰富的实际应用场景,如搜索引擎的构建、日志分析、企业知识库的搭建等,让读者能将理论知识应用于实践。 7. **Java编程**:作为一本面向Java开发者的书籍,书中所有示例都用Java编写,这...

    lucene 数据库

    通过这份文档,你可以了解到Lucene的基本概念,如索引的构建、查询解析以及结果排序等。作者分享了在实际操作中遇到的问题和解决方法,对于初学者来说,这是一份宝贵的实战经验总结。 接着是《Lucene的系统结构.doc...

    lucene 全包 包括源码

    这些模块共同构成了Lucene的基本架构。 1. 分析(Analyzer):Analyzer是处理文本输入的关键部分,负责将用户输入的文本拆分成可搜索的词项(Tokens)。它包括词项分割、标准化(如去除停用词、词干提取)等步骤。...

    LuceneDemo

    一、Lucene的基本概念 1. 文档(Document):在Lucene中,文档是信息的基本单位,可以理解为数据库中的记录。一个文档包含多个字段(Field),每个字段都有自己的名称和值,如标题、内容、作者等。 2. 字段(Field...

    lucene 代码

    1. **Lucene基本组件**: - **索引(Indexing)**: Lucene首先将文档内容转化为可搜索的结构——索引。这个过程包括分词(Tokenization)、词干提取(Stemming)、停用词处理(Stopword Removal)等步骤。 - **...

    apache下的lucene教程

    ### Apache Lucene教程知识点概述 #### 一、Apache Lucene简介 - **Lucene定义**:Lucene是一款高性能、全功能的文本搜索引擎库,由Java编写而成,是Apache基金会下的一个开源项目。 - **发展历程**:自1999年由...

    ssh+lucene搜索实例

    SSH(Secure Shell)是一种网络协议,用于在不安全的网络上提供安全的远程...以上就是关于"ssh+lucene搜索实例"的相关知识点,通过这种方式,可以有效地在分布式环境中实现全文搜索功能,提高数据检索的效率和便利性。

Global site tag (gtag.js) - Google Analytics