1.new Field("id", package.Id.ToString(), Field.Store.YES, Field.Index.TOKENIZED)
几个字段解析,“id”:索引字段的KEY,package.Id.ToString(),索引的值, Field.Store.YES,是否将值存入,如果是NO,该字段值无法提取出,Field.Index.TOKENIZED这个意思是是否建立索引,如果建立索引是否参与分词,TOKENIZED是参与分词,UN_TOKENIZED是不参与分词,直接全词索引,如果不希望改字段被分词最好选用这个属性。
2.如何判断所以是否建立成功,最基本的方法,查看索引创建时的索引数据文件,800多条数据几百K总是要有的。
3. 索引建立成功,查询时最简单的某字段TERM查询查询不出该结果,怎么办?
由于LUCENE查询时全词匹配,如果某字段按原值(如Name:)查询没有结果,首先要想到是否该字段被分词解析开了,比如:中华人民共和国,用标准分词器就会拆分成:中 华 人 民 共 盒国 一个字一个索引,你要按照中华查就或者原词查都查不到。这里有2个办法,1:在创建索引时将Field.Index.UN_TOKENIZED这样改字段就不参与分词,2:如果你整个需求没有太多分词的要求,或者分词的要求很明确有规律(比如按‘,’按‘ ’)分词,那可以自己重写一个分词器:
public class EsayTooTokenizer : CharTokenizer { public EsayTooTokenizer(TextReader reader) : base(reader) { } //单纯按照“,” 空格 分词 protected override bool IsTokenChar(char c) { return c == ',' || c == ' ' ? false : true; } } public class EsayTooAnalyzer : Analyzer { public override TokenStream TokenStream(string fieldName, System.IO.TextReader reader) { return new EsayTooTokenizer(reader); } }
以上就是单纯只按照逗号跟空格分词。
如果不知道分词结果,可以借鉴一下我写的分词器测试方法:
public static void ShowAnalyzerResult(Analyzer analyzer, String s) { StringReader reader = new StringReader(s); TokenStream ts = analyzer.TokenStream(s, reader); var t = ts.Next(); while (t != null) { Console.WriteLine(t.TermText() + " "); t = ts.Next(); } Console.WriteLine(); }
//调用方法
Analyzer analyzer1 = new EsayTooAnalyzer();
ShowAnalyzerResult(analyzer1, "大灯 (左)432");
ShowAnalyzerResult(analyzer1, "A43243 24321");
ShowAnalyzerResult(analyzer1, "这个事,情我怎么看啊");
4.索引更新问题,这个是我在开发时候碰到的,使用IndexWriter新增索引数据,调试的时候发现初始化时候索引正常添加,但是每次新增索引数据时就会复制一份.cfs文件然后对该文件增加索引,源文件始终是不动,再试了N多方法之后发现原来是我查询的IndexSearcher采用了一个静态的对象,只要查询过数据之后这个对象就会占用.cfs文件,这时在做更新就会新增一个缓存CFS文件,导致缓存查询失败。 解决方案:每次查询时候新建IndexSearcher,并在查询语句之后把它CLOSE();
5.IndexReader.DeleteDocuments(Term) 相关POST
Lucene删除索引DeleteDocuments的注意事项
Lucene在删除索引时,经常会出现代码成功执行,但索引并未正直删除的现象,总结一下,要注意以下因素:
1.在创建Term时,注意Term的key一定要是以"词"为单位,否则删除不成功,例如:添加索引时,如果把"d:\doc\id.txt"当作要索引的字符串索引过了,那么在删除时,如果直接把"d:\doc\id.txt"作为查询的key来创建Term是无效的,应该用Id.txt(但这样会把所有文件名为Id.txt的都删除,所以官方建议最好用一个能唯一标识的关键字来删除,比如产品编号,新闻编号等(我的猜想:每个document都加入一个id字段作为唯一标识(可用系统当前时间值作为id的值),每当要删除包含某关键字的文档索引时,先将这些文档搜索出来,然后获取它们的id值,传给一个List,然后再用List结合id字段来删除那些文档的索引......不过这个方法的效率可能会低了一点,因为每个文档都要搜两遍);
2.要删除的“词”,在创建索引时,一定要是Tokened过的,否则也不成功;
3.IndexReader,IndexModifer,IndexWriter都提供了DeleteDocuements方法,但建议用 IndexModifer来操作,原因是IndexModifer内部做了很多线程安全处理;
4.删除完成后,一定要调用相应的Close方法,否则并未真正从索引中删除。