Lucene.net 系列三 --- index 中

Lucene.net 系列三 --- index 中 本文将进一步讨论有关Lucene.net建立索引的问题:
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中主要包含以下主题:
Lucene.net 系列三 --- index 中
1 .索引的权重
Lucene.net 系列三 --- index 中
2 .利用IndexWriter 属性对建立索引进行高级管理
Lucene.net 系列三 --- index 中
3 .利用RAMDirectory充分发挥内存的优势
Lucene.net 系列三 --- index 中
4 .利用RAMDirectory并行建立索引
Lucene.net 系列三 --- index 中
5 .控制索引内容的长度
Lucene.net 系列三 --- index 中
6 .Optimize 优化的是什么 ?
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中源代码下载
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中本文将进一步讨论有关Lucene.net建立索引的问题:
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中索引的权重
Lucene.net 系列三 --- index 中根据文档的重要性的不同,显然对于某些文档你希望提高权重以便将来搜索的时候,更符合你想要的结果. 下面的代码演示了如何提高符合某些条件的文档的权重.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中比如对公司内很多的邮件做了索引,你当然希望主要查看和公司有关的邮件,而不是员工的个人邮件.这点根据邮件的地址就可以做出判断比如包含@alphatom.com的就是公司邮件,而@gmail.com等等就是私人邮件.如何提高相应邮件的权重
?  代码如下:
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中     
public   static   String COMPANY_DOMAIN  =   " alphatom.com " ;
Lucene.net 系列三 --- index 中     Document doc 
=   new  Document();
Lucene.net 系列三 --- index 中     String senderEmail 
=  GetSenderEmail();
Lucene.net 系列三 --- index 中     String senderName 
=  getSenderName();
Lucene.net 系列三 --- index 中     String subject 
=  GetSubject();
Lucene.net 系列三 --- index 中     String body 
=  GetBody();
Lucene.net 系列三 --- index 中     doc.Add(Field.Keyword(
" senderEmail”, senderEmail));
Lucene.net 系列三 --- index 中
     doc.Add(Field.Text( " senderName " , senderName));
Lucene.net 系列三 --- index 中     doc.Add(Field.Text(
" subject " , subject));
Lucene.net 系列三 --- index 中     doc.Add(Field.UnStored(
" body " , body)); 
Lucene.net 系列三 --- index 中     
if  (GetSenderDomain().EndsWith(COMPANY_DOMAIN)) 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中    
// 如果是公司邮件,提高权重,默认权重是1.0
Lucene.net 系列三 --- index 中
           doc.SetBoost( 1.5 );                       
Lucene.net 系列三 --- index 中     
else                           // 如果是私人邮件,降低权重.
Lucene.net 系列三 --- index 中
           doc.SetBoost( 0.1 );
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中     writer.AddDocument(doc); 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中不仅如此你还可以对Field也设置权重.比如你对邮件的主题更感兴趣.就可以提高它的权重.    
Lucene.net 系列三 --- index 中    Field senderNameField 
=  Field.Text( " senderName " , senderName);
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中     Field subjectField 
=  Field.Text( " subject " , subject);
Lucene.net 系列三 --- index 中     subjectField.SetBoost(
1.2 );
Lucene.net 系列三 --- index 中lucene搜索的时候会对符合条件的文档按匹配的程度打分,这点就和google的PageRank有点类似, 而SetBoost中的Boost就是其中的一个因素,当然还有其他的因素.这要放到搜索里再说. 
Lucene.net 系列三 --- index 中利用IndexWriter 变量对建立索引进行高级管理
Lucene.net 系列三 --- index 中在建立索引的时候对性能影响最大的地方就是在将索引写入文件的时候, 所以在具体应用的时候就需要对此加以控制.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中在建立索引的时候对性能影响最大的地方就是在将索引写入文件的时候所以在具体应用的时候就需要对此加以控制 IndexWriter属性   
Lucene.net 系列三 --- index 中 默认值
Lucene.net 系列三 --- index 中 描述
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中MergeFactory
Lucene.net 系列三 --- index 中 
10
Lucene.net 系列三 --- index 中 控制segment合并的频率和大小
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中MaxMergeDocs
Lucene.net 系列三 --- index 中 Int32.MaxValue
Lucene.net 系列三 --- index 中 限制每个segment中包含的文档数
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中MinMergeDocs
Lucene.net 系列三 --- index 中 
10
Lucene.net 系列三 --- index 中 当内存中的文档达到多少的时候再写入segment
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中Lucene默认情况是每加入10份文档就从内存往index文件写入并生成一个segement,然后每10个segment就合并成一个segment.通过MergeFactory这个变量就可以对此进行控制. 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中MaxMergeDocs用于控制一个segment文件中最多包含的Document数.比如限制为100的话,即使当前有10个segment也不会合并,因为合并后的segmnet将包含1000个文档,超过了限制.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中MinMergeDocs用于确定一个当内存中文档达到多少的时候才写入文件,该项对segment的数量和大小不会有什么影响,它仅仅影响内存的使用,进一步影响写索引的效率.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中为了生动的体现这些变量对性能的影响,用一个小程序对此做了说明. 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中这里有点不可思议.Lucene 
in  Action书上的结果比我用dotLucene做的结果快了近千倍.这里给出书中用Lucene的数据,希望大家比较一下看看是不是我的问题.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中Lucene 
in  Action书中的数据:
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
%  java lia.indexing.IndexTuningDemo  100000   10   9999999   10
Lucene.net 系列三 --- index 中Merge factor: 
10
Lucene.net 系列三 --- index 中Max merge docs: 
9999999
Lucene.net 系列三 --- index 中Min merge docs: 
10
Lucene.net 系列三 --- index 中Time: 
74136  ms
Lucene.net 系列三 --- index 中
%  java lia.indexing.IndexTuningDemo  100000   100   9999999   10
Lucene.net 系列三 --- index 中Merge factor: 
100
Lucene.net 系列三 --- index 中Max merge docs: 
9999999
Lucene.net 系列三 --- index 中Min merge docs: 
10
Lucene.net 系列三 --- index 中Time: 
68307  ms
Lucene.net 系列三 --- index 中我的数据: 
336684128  ms
Lucene.net 系列三 --- index 中可以看出MinMergeDocs(主要用于控制内存)和MergeFactory(控制合并的次数和合并后的大小) 对建立索引有显著的影响.但是并不是MergeFactory越大越好,因为如果一个segment的文档数很多的话,在搜索的时候必然也会影响效率,所以这里MergeFactory的取值是一个需要平衡的问题.而MinMergeDocs主要受限于内存.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中利用RAMDirectory充分发挥内存的优势
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中从上面来看充分利用内存的空间,减少读写文件(写入index)的次数是优化建立索引的重要方法.其实在Lucene中提供了更强大的方法来利用内存建立索引.使用RAMDirectory来替代FSDirectory. 这时所有的索引都将建立在内存当中,这种方法对于数据量小的搜索业务很有帮助,同时可以使用它来进行一些小的测试,避免在测试时频繁建立删除索引文件.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中在实际应用中RAMDirectory和FSDirectory协作可以更好的利用内存来优化建立索引的时间.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中具体方法如下:
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
1 .建立一个使用FSDirectory的IndexWriter
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
2  .建立一个使用RAMDirectory的IndexWriter 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
3  把Document添加到RAMDirectory中
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
4  当达到某种条件将RAMDirectory 中的Document写入FSDirectory.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
5  重复第三步 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中示意代码:
Lucene.net 系列三 --- index 中      
private  FSDirectory fsDir  =  FSDirectory.GetDirectory( " index " , true );  
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中       
private  RAMDirectory ramDir  =   new  RAMDirectory();
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中       
private  IndexWriter fsWriter  =  IndexWriter(fsDir, new  SimpleAnalyzer(),  true );
Lucene.net 系列三 --- index 中       
private  IndexWriter ramWriter  =   new  IndexWriter(ramDir, new  SimpleAnalyzer(),  true );
Lucene.net 系列三 --- index 中       
while  (there are documents to index) 
Lucene.net 系列三 --- index 中      
{
Lucene.net 系列三 --- index 中         ramWriter.addDocument(doc);
Lucene.net 系列三 --- index 中         
if (condition for flushing memory to disk has been met) 
Lucene.net 系列三 --- index 中         
{
Lucene.net 系列三 --- index 中           fsWriter.AddIndexes(Directory[]
{ramDir}) ;
Lucene.net 系列三 --- index 中           ramWriter.Close();          
//why not support flush?
Lucene.net 系列三 --- index 中
           ramWriter =new IndexWriter(ramDir,new SimpleAnalyzer(),true);
Lucene.net 系列三 --- index 中         }

Lucene.net 系列三 --- index 中     }
 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中这里的条件完全由用户控制,而不是FSDirectory采用对Document计数的方式控制何时写入文件.相比之下有更大的自由性,更能提升性能.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中利用RAMDirectory并行建立索引
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中RAMDirectory还提供了使用多线程来建立索引的可能性.下面这副图很好的说明了这一点.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中   
Lucene.net 系列三 --- index 中甚至你可以在一个高速的网络里使用多台计算机来同时建立索引.就像下面这种图所示.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中虽然有关并行同步的问题需要你自己进行处理,不过通过这种方式可以大大提高对大量数据建立索引的能力.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中控制索引内容的长度.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中在我的一篇速递介绍过Google Desktop Search只能搜索到文本中第5000个字的.也就是google在建立索引的时候只考虑前5000个字,在Lucene中同样也有这个配置功能.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中Lucene对一份文本建立索引时默认的索引长度是10,
000 . 你可以通过IndexWriter 的MaxFieldLength属性对此加以修改.还是用一个例子说明问题. 
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中     [Test]
Lucene.net 系列三 --- index 中     
public   void  FieldSize()       
Lucene.net 系列三 --- index 中     
//  AddDocuments 和 GetHitCount都是自定义的方法,详见源代码
Lucene.net 系列三 --- index 中
      {
Lucene.net 系列三 --- index 中         AddDocuments(dir, 
10);       
Lucene.net 系列三 --- index 中         
//第一个参数是目录,第二个配置是索引的长度
Lucene.net 系列三 --- index 中
         Assert.AreEqual(1, GetHitCount("contents""bridges"))
Lucene.net 系列三 --- index 中         
//原文档的contents为”Amsterdam has lots of bridges”
Lucene.net 系列三 --- index 中         
//当索引长度为10个字时能找到bridge
Lucene.net 系列三 --- index 中
         AddDocuments(dir, 1);
Lucene.net 系列三 --- index 中         Assert.AreEqual(
0, GetHitCount("contents""bridges"));
Lucene.net 系列三 --- index 中         
//当索引长度限制为1个字时就无法发现第5个字bridges
Lucene.net 系列三 --- index 中
     }

Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中   对索引内容限长往往是处于效率和空间大小的考虑.能够对此进行配置是建立索引必备的一个功能.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中Optimize 优化的是什么
?
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中在以前的例子里,你可能已经多次见过writer.Optimize()这段代码.Optimize到底做了什么
?
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中让你吃惊的是这里的优化对于建立索引不仅没有起到加速的作用,反而是延长了建立索引的时间.为什么
?
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中因为这里的优化不是为建立索引做的,而是为搜索做的.之前我们提到Lucene默认每遇到10个Segment就合并一次,尽管如此在索引完成后仍然会留下几个segmnets,比如6,
7 .
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中而Optimize的过程就是要减少剩下的Segment的数量,尽量让它们处于一个文件中.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中它的过程很简单,就是新建一个空的Segmnet,然后把原来的几个segmnet全合并到这一个segmnet中,在此过程中,你的硬盘空间会变大,因为同时存在两份一样大小的索引.不过在优化完成后,Lucene会自动将原来的多份Segments删除,只保留最后生成的一份包含原来所有索引的segment.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中尽量减少segments的个数主要是为了增加查询的效率.假设你有一个Server,同时有很多的Client建立了各自不同的索引,如果此时搜索,那么必然要同时打开很多的索引文件,这样显然会受到很大的限制,对性能产生影响.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中当然也不是随时做Optimize就好,如前所述做优化时要花费更多的时间和空间,而且在做优化的时候是不能进行查询的.所以索引建立的后期,并且索引的内容不会再发生太多的变化的时候做优化是一个比较好的时段.
Lucene.net 系列三 --- index 中
Lucene.net 系列三 --- index 中

你可能感兴趣的:(Lucene)