记得是看了某位大虾的blog整理的,可是现在也忘记了这位好人,在次表示感谢这为无名英雄.
lucene学习笔记:
(一)Query
1.TermQuey//查询特定的某个Field
//过程:
Term t = new Term("subject", "ant");
//Term构造函数的参数:param1是Field名,param2是用户查询的关键字
Query query = new TermQuery(t);
Hits hits = searcher.Search(query);
2.QueryParse//简化查询语句
//过程:
Query query = QueryParser.Parse("+JUNIT +ANT -MOCK","contents",new SimpleAnalyzer());
Hits hits = searcher.Search(query);
//注意:TermQuery和QueryParse只要在QueryParse的Parse方法中只有一个word,就会自动转换成TermQuery.
3.RangeQuery//范围查询,用于查询范围,通常用于时间
//过程:
RangeQuery query = new RangeQuery(begin, end, true);
Hits hits = searcher.Search(query);
//RangeQuery的第三个参数用于表示是否包含该起止日期.Lucene用[] 和{}分别表示包含和不包含.RangeQuery到QueryParse的转化
//Query query = QueryParser.Parse("pubmonth:[200004 TO 200206]", "subject", new SimpleAnalyzer());
//IndexSearcher searcher = new IndexSearcher(directory);
//Hits hits = searcher.Search(query);
4.PrefixQuery//搜索是否包含某个特定前缀
PrefixQuery query = new PrefixQuery(new Term("category", "/Computers"));
Hits hits = searcher.Search(query);
5.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表示可以满足该条件.
//BooleanQuery和QueryParse
[Test]
public void TestQueryParser()
{
Query query = QueryParser.Parse("pubmonth:[200301 TO 200312] AND junit", "subject", new SimpleAnalyzer());
IndexSearcher searcher = new IndexSearcher(directory);
Hits hits = searcher.Search(query);
Assert.AreEqual(1, hits.Length());
query = QueryParser.Parse("/Computers/JUnit OR /Computers/Ant", "category", new WhitespaceAnalyzer());
hits = searcher.Search(query);
Assert.AreEqual(2, hits.Length());
}
//注意AND和OR的大小 如果想要A与非B 就用 A AND –B 表示, +A –B也可以.
//默认的情况下QueryParser会把空格认为是或关系,就象google一样.但是你可以通过QueryParser对象修改这一属性.
[Test]
public void TestQueryParserDefaultAND()
{
QueryParser qp = new QueryParser("subject", new SimpleAnalyzer());
qp.SetOperator(QueryParser.DEFAULT_OPERATOR_AND );
Query query = qp.Parse("pubmonth:[200301 TO 200312] junit");
IndexSearcher searcher = new IndexSearcher(directory);
Hits hits = searcher.Search(query);
Assert.AreEqual(1, hits.Length());
}
6.PhraseQuery//短语查询
7.WildcardQuery//通配符搜索
8.FuzzyQuery//模糊查询
(二)Analyzer
WhitespaceAnalyzer:仅仅是去除空格,对字符没有lowcase化,不支持中文
SimpleAnalyzer:功能强于WhitespaceAnalyzer,将除去letter之外的符号全部过滤掉,并且将所有的字符lowcase化,
不支持中文
StopAnalyzer:StopAnalyzer的功能超越了SimpleAnalyzer,在SimpleAnalyzer的基础上
增加了去除StopWords的功能,不支持中文
StandardAnalyzer:英文的处理能力同于StopAnalyzer.支持中文采用的方法为单字切分.
ChineseAnalyzer:来自于Lucene的sand box.性能类似于StandardAnalyzer,缺点是不支持中英文混和分词.
CJKAnalyzer:chedong写的CJKAnalyzer的功能在英文处理上的功能和StandardAnalyzer相同
但是在汉语的分词上,不能过滤掉标点符号,即使用二元切分
最强大的分析程序——StandardAnalyzer类。
StandardAnalyzer类会将文本的所有内容变成小写的,并去掉一些常用的停顿词(stop word)。
停顿词是像“a”、“the”和“in”这样的词,它们都是内容里非常常见的词,但是对搜索却一点用处都没有。
分析程序也会分析搜索查询,这就意味着查询会找到匹配的部分。例如,
这段文本“The dog is a golden retriever(这条狗是一只金毛猎犬)”,
就会被处理为“dog golden retriever”作为索引。当用户搜索“a Golden Dog”的时候,
分析程序会处理这个查询,并将其转变为“golden dog”,这就符合我们的内容了。
(三)性能问题
1.切词,索引,存属
域存储字段规则
方法 切词 索引 存储 用途
Field.Text(String name, String value) 切分词索引并存储,比如:标题,内容字段
Field.Text(String name, Reader value) 切分词索引不存储,比如:META信息,
不用于返回显示,但需要进行检索内容
Field.Keyword(String name, String value) 不切分索引并存储,比如:日期字段
Field.UnIndexed(String name, String value) 不索引,只存储,比如:文件路径
Field.UnStored(String name, String value) 只全文索引,不存储
-----------------------------------------------------------------------------------------------
Keywork
该类型的数据将不被分析,而会被索引并保存保存在索引中.
UnIndexed
该类型的数据不会被分析也不会被索引,但是会保存在索引.
UnStored
和UnIndexed刚好相反,被分析被索引,但是不被保存.
Text
和UnStrored类似.如果值的类型为string还会被保存.如果值的类型Reader就不会被保存和UnStored一样.
2.优化索引生成文件
1.索引的权重SetBoost
if (GetSenderDomain().EndsWith(COMPANY_DOMAIN))
//如果是公司邮件,提高权重,默认权重是1.0
doc.SetBoost(1.5);
else
//如果是私人邮件,降低权重.
doc.SetBoost(0.1);
不仅如此你还可以对Field也设置权重.比如你对邮件的主题更感兴趣.就可以提高它的权重.
Field senderNameField = Field.Text("senderName", senderName);
Field subjectField = Field.Text("subject", subject);
subjectField.SetBoost(1.2);
2.利用IndexWriter 属性对建立索引进行高级管理
在建立索引的时候对性能影响最大的地方就是在将索引写入文件的时候所以在具体应用的时候就需要对此加以控制
IndexWriter属性
描述 默认值 备注
MergeFactory 10 控制segment合并的频率和大小
MaxMergeDocs Int32.MaxValue 限制每个segment中包含的文档数
MinMergeDocs 10 当内存中的文档达到多少的时候再写入segment
Lucene默认情况是每加入10份文档就从内存往index文件写入并生成一个segement,然后每10个segment就合并成一个segment.通过MergeFactory这个变量就可以对此进行控制.
MaxMergeDocs用于控制一个segment文件中最多包含的Document数.比如限制为100的话,即使当前有10个segment也不会合并,因为合并后的segmnet将包含1000个文档,超过了限制.
MinMergeDocs用于确定一个当内存中文档达到多少的时候才写入文件,该项对segment的数量和大小不会有什么影响,它仅仅影响内存的使用,进一步影响写索引的效率.
3.利用RAMDirectory充分发挥内存的优势
在实际应用中RAMDirectory和FSDirectory协作可以更好的利用内存来优化建立索引的时间.
具体方法如下:
1.建立一个使用FSDirectory的IndexWriter
2.建立一个使用RAMDirectory的IndexWriter
3. 把Document添加到RAMDirectory中
4. 当达到某种条件将RAMDirectory 中的Document写入FSDirectory.
5. 重复第三步
示意代码:
private FSDirectory fsDir = FSDirectory.GetDirectory("index",true);
private RAMDirectory ramDir = new RAMDirectory();
private IndexWriter fsWriter = IndexWriter(fsDir,new SimpleAnalyzer(), true);
private IndexWriter ramWriter = new IndexWriter(ramDir,new SimpleAnalyzer(), true);
while (there are documents to index)
{
ramWriter.addDocument(doc);
if (condition for flushing memory to disk has been met)
{
fsWriter.AddIndexes(Directory[]{ramDir}) ;
ramWriter.Close(); //why not support flush?
ramWriter =new IndexWriter(ramDir,new SimpleAnalyzer(),true);
}
}
这里的条件完全由用户控制,而不是FSDirectory采用对Document计数的方式控制何时写入文件.
相比之下有更大的自由性,更能提升性能.
4.控制索引内容的长度
Lucene对一份文本建立索引时默认的索引长度是10,000. 你可以通过IndexWriter 的MaxFieldLength属性对此加以修改.还是用一个例子说明问题.
5.Optimize 优化
=------------------------jackstudio-----------------
posted on 2006-03-31 14:01
jackstudio 阅读(1003)
评论(0) 编辑 收藏 所属分类:
java