Lucene.NET 若干知识点&&疑难杂症以及解决
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(); } <br> //调用方法<br> Analyzer analyzer1 = new EsayTooAnalyzer();<br> ShowAnalyzerResult(analyzer1, "大灯 (左)432");<br> ShowAnalyzerResult(analyzer1, "A43243 24321");<br> 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方法,否则并未真正从索引中删除。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步