如何在Lucene.Net中一个Document使用不同的分词(一)

时间:2022-10-21 03:16:08
这是在博客园Lucene.Net小组看到的一个问题。呵呵,尝试用以下方法解决。
说明:代码没有经过测试。


在Lucene.Net中一个Document对象创建并不涉及到分词,分词是跟IndexWriter相关的。

以类库自带的StandardAnalyzer分词举例,创建一个索引的过程如下

/*  实例化写入  */
IndexWriter writer 
=   new  IndexWriter( new  Lucene.Net.Analysis.Standard.StandardAnalyzer(), true );
/*  建立文档  */
Document doc 
=   new  Document();
doc.Add(
new  Field( " id " " 123 " , Field.Store.YES, Field.Index.TOKENIZED));
doc.Add(
new  Field( " title " " 这个是标题 " , Field.Store.YES, Field.Index.TOKENIZED));
doc.Add(
new  Field( " content " " 这个是内容 " , Field.Store.YES, Field.Index.TOKENIZED));
/*   写入文档  */
writer.AddDocument(doc);
/*  优化索引结构  */
writer.Optimize();
/*  关闭写入  */
writer.Close();

在这样的代码里想一个文档不同字段使用不同分词是不可能的。如果要让每个字段使用不同分词,那么当然是给每个字段加上分词器属性。

先找到Lucene.Net的Field类,发现Field类的字段是继承自AbstractField父类的。在AbstractField先加上
protected internal Analysis.Analyzer analyzer;

然后增加一个构造函数:
         protected   internal  AbstractField( string  name, Field.Store store, Field.Index index, Field.TermVector termVector, Analysis.Analyzer analyzer)
            : 
this (name, store, index, termVector)
        {
            
this .analyzer  =  analyzer;
        }

在Field类增加构造函数:
         public  Field(System.String name, System.String value_Renamed, Store store, Index index, TermVector termVector, Analysis.Analyzer analyzer)
            : 
base (value_Renamed, store, index, termVector, analyzer)
        {

        }


在接口Fieldable中增加方法GetAnalyzer;
Analysis.Analyzer GetAnalyzer();


并且在AbstractField类中实现GetAnalyzer方法:

         public   virtual  Analysis.Analyzer GetAnalyzer()
        {
            
return   this .analyzer;
        }

修改DocumentWriter类的 179行 ,如果因为版本不一样不在179行,请查找
“TokenStream stream = analyzer.TokenStream(fieldName, reader);”

然后换成

TokenStream stream = field.GetAnalyzer().TokenStream(fieldName, reader);

OK,写入的部分搞定了,读取的部分明天再弄。

现在就可以这么用了:

/*  实例化写入  */
IndexWriter writer 
=   new  IndexWriter( new  Lucene.Net.Analysis.Standard.StandardAnalyzer(), true );
/*  建立文档  */
Document doc 
=   new  Document();
doc.Add(
new  Field( " id " " 123 " , Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO,  new  Lucene.Net.Analysis.KeywordAnalyzer()));
doc.Add(
new  Field( " title " " 这个是标题 " , Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO,  new  Lucene.Net.Analysis.Standard.StandardAnalyzer()));
doc.Add(
new  Field( " content " , " 这个是内容 " , Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO,  new  Lucene.Net.Analysis.SimpleAnalyzer()));
/*   写入文档  */
writer.AddDocument(doc);
/*  优化索引结构  */
writer.Optimize();
/*  关闭写入  */
writer.Close();

当然,这个时候,IndexWriter 的分词器实际上是无用的,也可以判定Field给定的分词器是否为null,然后用IndexWriter 的作为默认分词器。

by yurow @ http://www.cnblogs.com/birdshover/

更新第二部分地址: 如何在Lucene.Net中一个Document使用不同的分词(二)