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();
        } 

//调用方法
            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

2010-02-19 23:30

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方法,否则并未真正从索引中删除。

原文地址:https://www.cnblogs.com/vinnie520/p/2559033.html