DotLucene(Lucene.Net)研究[转]
1. 新建工程
a) 引用Lucene.Net.dll
using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
2. 创建索引(Creating an index)
在你开始进行搜索之前,你需要创建一个的索引,并且添加你想搜索的数据
a) .创建索引使用一个名叫 IndexWriter的类
IndexWriter writer = new IndexWriter(@"C:\your\index\directory", new StandardAnalyzer(), true);
这样很轻松的在硬盘目录中创建了一个新的索引(你需要对硬盘写的权限);你也可以存储索引到内存中或者数据库中
b) 然后,当你创建索引之后,你可以打开它,当你需要向其添加文档时.
IndexWriter writer = new IndexWriter(@"C:\your\index\directory", new StandardAnalyzer(), false);
3. 添加文档到索引中
一旦你打开索引后,你可以向其添加文档.你向索引中插入的每一个实体都是一个文档.在索引中的每一个域都包含了相关的信息.在每一个域你需要特别的编录它,那就意味着无论域满足下面:
stored in the index(你可以得到任何存储值从索引中,这个对短域很有用,例如:author,title,等)
indexed(编录索引对于你想请求的域来说是必须的)
tokenized(标记,分割单词在编录之前)
域可以列入有用的构造:
public Field(string fieldName, string fieldValue, bool stored, bool indexed, bool tokenized);
为了你使用方便,这里也可以使用静态的方法创建一个新的域实例:
Field.Keyword() –域值存储和编录,但是不作标记
Field.Text(string name,StreamReader val) –域不被存储,但是可以编录索引 和作标记
Field.Text(string name,string val)—域被存储,编入索引,标记
Field.UnIndexed() –域仅仅被存储
如果你向获取标记值和编录索引,你需要无格式文本支持.为了编入其它格式化的文本,你需要一个分词器.我们将查看一个剖析一个HTML文档
在我们的例子中,我们将编录索引一个文本文件,让我们使用这些域:
“filename” (存储,不编入索引,不标记)
“text”(不存储,编入索引,标记)
当我们使用这样的域,我们可以仅仅搜索这些内容(“text”域)
void addDocument(IndexWriter writer, string path)
{
Document doc = new Document();
StreamReader sr = new StreamReader(path, System.Text.Encoding.Default);
doc.Add(Field.Text("text", sr));
doc.Add(Field.Keyword("filename", path));
writer.AddDocument(doc);
sr.Close();
}
4.保存索引
不要忘记保存索引
writer.Close();
你可以在关闭IndexWriter之前有很索引
writer.Optimize();
writer.Close();
优化可能花费一些时间,但是可以提高搜索性能.你应该在索引写操作完成之前进行优化.
5.开始搜索
当你搜索一个搜索索引之前,你首先应该使用IndexSearcher ,你可以打开它,并且执行搜索,当那里有另外一个添加文档过程或者优化.
IndexSearcher searcher = new IndexSearcher(@"C:\your\index\directory");
然后你可以创建查询:
string q = "dotlucene";
Query query = QueryParser.Parse(q, "text", new StandardAnalyzer());
现在可以获取搜索结果并且打印出来.我们职能将文件名打印出来,因为我们在索引中每一存储其它域.
Hits hits = searcher.Search(query);
Console.WriteLine("Found " + hits.Length() + " document(s) that matched query '" + q + "':\r\n");
for (int i = 0; i < hits.Length(); i++) {
Document doc = hits.Doc(i);
Console.WriteLine(doc.Get("filename") + "\r\n");
}
最后别忘记关闭搜索引擎:
searcher.Close();
6. Query syntax(查询语法)
Query |
Example |
Notes |
single term 单词 |
document |
Searches for documents that contain "document" term in the default field. 搜索文档中包含”document”单词的默认域 |
Phrase 短语 |
"important document" |
Searches for documents that contain the phrase "important document" in the default fiels. 搜索文档中包含” important document”短语的默认域 |
searching fields 搜索域 |
title:document |
Searches for documents that contain "document" term in the "title" field. 搜索文档中”title”域中包含单词” document” |
wildcard search 通配符搜索 |
doc?ment |
Single-character wildcard search. It will match "document" and "dociment" but not "docooment". 当字母通配符查询,它将匹配” document”和” dociment”,但不匹配”docooment” |
|
document* |
Multi-character wildcard search. It will match "document" and "documentation". 多字母通配符查询,它将匹配” document”和” documentation” |
fuzzy search 模糊查询 |
document~ |
Search based on similar spelling. 查询基本相似的拼写 |
|
document~0.9 |
Search based on similar spelling. 0.9 is the required similarity (default: 0.5) 查询相似度为0.9的,默认0.5 |
proximity search 接近查询 |
"important document"~5 |
Find words of a phrase that are not next to each other. Maximum distance in this example is 5 words. 查找短语中的单词,在接下来的短语中,最远距离为5个单词 |
range search 范围查询 |
author:{Einstein TO Newton} |
Searches for document with "author" field value between specified values. 查询文档中域”author”值在清单值之间. |
|
date:{20050101 TO 20050201} |
Searches for document with "date" field (DateTime type) value between specified dates. 查询文档中域”date”(日期型)在清单值之间 |
Relevance 适当 |
important^4 document |
Set boost factor of the term "important" to 4. Default boost factor is 1. |
|
"important document"^4 "search engine" |
You can set boost factor for phrases too. |
OR operator 或操作 |
important document |
"OR" is the default operator. |
|
important OR document |
The default field must contain either "important" or "document". 默认文档中必须包含” important” 或者” document” |
AND operator 与操作 |
important AND document |
The default field must contain both word. 默认文档必须包含所有的单词 |
+ operator +操作 |
important +document |
The default field must contain "document" and may contain "important". 默认文档必须包含”document” 并且可以包含” important” |
NOT/- operator 非操作 |
-important document |
The default field must contain "document" but not "important". 默认文档必须包含” document” 但是不保存” important” |
Grouping 分组 |
(important OR office) AND document |
Use parentheses for expression grouping. 使用园括弧分组 |
|
author:(Einstein OR Newton) |
Parentheses work with fields as well. |
7. Prohibited Queries(禁止查询)
Query |
Examples |
Notes |
wildcard at the beginning of a term 通配符在一个单词的开始 |
?ocument, *ocument |
Throws Lucene.Net.QueryParsers.ParseException. |
stop words 逗号 |
a, the, and |
Stop words are not indexed. |
special characters: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ 特殊字符 |
\+, \:
|
Use a backslash to escape the special characters. |
学习积累:
1. TermQuery 查询某个特定的词
Term t = new Term("isbn", "1930110995");
Query query = new TermQuery(t);
2.RangeQuery 用于查询范围,通常用于时间查询
例如: Query query=new RangeQuery(new Term("time","20070516"),new Term("time","20070517"),false);
RangeQuery的第三个参数用于表示是否包含该起止日期
3. PrefixQuery 用于搜索是否包含某个特定前缀,常用于Catalog的检索.
PrefixQuery query = new PrefixQuery(new Term("category", "/Computers"));
4. BooleanQuery 用于测试满足多个条件.
TermQuery searchingBooks =
new TermQuery(new Term("subject", "junit"));
RangeQuery currentBooks =
new RangeQuery(new Term("pubmonth", "200301"),
new Term("pubmonth", "200312"),
true);
BooleanQuery currentSearchingBooks = new BooleanQuery();
currentSearchingBooks.Add(searchingBooks, true, false);
currentSearchingBooks.Add(currentBooks, true, false);
IndexSearcher searcher = new IndexSearcher(directory);
Hits hits = searcher.Search(currentSearchingBooks);
什么时候是与什么时候又是或? 关键在于BooleanQuery对象的Add方法的参数.
参数一是待添加的查询条件.
参数二Required表示这个条件必须满足吗? True表示必须满足, False表示可以不满足该条件.
参数三Prohibited表示这个条件必须拒绝吗? True表示这么满足这个条件的结果要排除, False表示可以满足该条件.
注意AND和OR的大小 如果想要A与非B 就用 A AND –B 表示, +A –B也可以.
默认的情况下QueryParser会把空格认为是或关系,就象google一样.但是你可以通过QueryParser对象修改这一属性
5. PhraseQuery
查询短语,这里面主要有一个slop的概念, 也就是各个词之间的位移偏差,
这个值会影响到结果的评分.如果slop为0,当然最匹配.看看下面的例子就比较容易明白了,有关slop的计算用户就不需要理解了,不过slop太大的
时候对查询效率是有影响的,所以在实际使用中要把该值设小一点.
PhraseQuery对于短语的顺序是不管的,这点在查询时除了提高命中率外,也会对性能产生很大的影响,
利用SpanNearQuery可以对短语的顺序进行控制,提高性能.
private bool matched(String[] phrase, int slop)
{
PhraseQuery query = new PhraseQuery();
query.SetSlop(slop);
for (int i = 0; i < phrase.Length; i++)
{
query.Add(new Term("field", phrase[i]));
}
Hits hits = searcher.Search(query);
return hits.Length() > 0;
}
利用QueryParse进行短语查询的时候要先设定slop的值,有两种方式如下所示:
Query q2 = QueryParser.Parse(""quick fox"~1", //第一种方式
"field", new SimpleAnalyzer());
QueryParser qp = new QueryParser("field", new SimpleAnalyzer());
qp.SetPhraseSlop(1); //第二种方式
原文:http://www.shenjk.com/detail/277