Lucene可能生成这几种文件:
- Segments 这个文件记录着索引的有多少个segment,每个segment有多少个Document等信息
- Deletable 这个文件记录着删除的Document信息,这里就相当于一个回收站,只有等到合并索引或者对索引进行优化时才真正把Document删除掉。这些动作就相当于我们针对回收站执行删除操作彻底删除文件一个道理.
- *.fnm 这个是保存了*段的所有fieldName的信息
- *.fdx 这里保存的是指向*.fdt文件的指针
- *.fdt 这个文件其实就是保存的所有Field需要存储的数据.
- *.tii 这个是指向词条存储文件tis的指针
- *.tis 这个是存储词条的内容的文件
- *.cfs 这个是个综合文件,包含上面一个完整的*.fnm,*.fdx,*.fdt,*.tii,*.tis.这是个复合索引的文件格式
构建索引时的几种规则
- 是否存储
- 是否索引
- 是否分词
这里其实是三个基本规则,但是具体组合是通过Field的两个静态类Store,Index组合得出的
Store.NO:当前Field不进行存储
Stroe.YES:当前Field进行存储.这里存储就是存放在
Store.COMPRESS:如果传入的是二进制形式的内容,可以用这个参数来进行压缩存储.
Index.NO:不进行索引.
Index.TOKENIZED:进行索引,并且分词.
Index.UN_TOKENIZED:进行索引,但不分词.
Index.NO_NORMS:进行索引,但是不使用Analyzer,且不评分.
影响性能的一些设置
使用复合索引减少段文件数量,此时文件后缀变成一个.cfs的格式
IndexWriter.setUseCompoundFile(true);
合并段数量优化,将多个segment合并成一个segment.但是这个segment可能要符合一些规则
IndexWriter.optimize();
这些规则将影响索引的建立及性能:
- IndexWriter.setMergeFactor(mergeFactor)
- IndexWriter.setMaxMergeDocs(maxMergeDocs)
- IndexWriter.setMaxBufferedDocs(maxBufferedDocs)
- IndexWriter.setMaxFieldLength(maxFieldLength)
解释:
- mergeFactor:代表着对索引创建时什么时候生成新的segment的规则. 比如初始10个Document构成一个segment,当第11个Document被写入时,那么将创建一个新的segment,当写入了100个Document的时候,已经创建了10个segment了,而第101个Document被写入的时候,将不会创建第11个segment,而是将前10个segment合并成一个segment,这个segment包含100个Document,而第101个Document将被写入第二个segment,以此类推。所以这个因子,数值越大,segment增长的速度越慢.文件相对来说较少,数值越小,segment相对来说较多.
-
maxMergeDocs:由于segment的是按照mergeFactor因子的几何倍大小增长的,这样最终可能一个segment将包含很多Document,这样似乎不是很合理,所以maxMergeDocs就是控制一个segment最多包含的Document个数的值.
-
maxBufferedDocs 由于写入segment的时候所有的Document都在内存中,可能导致资源紧张,这个时候可以使用maxBufferedDocs来控制内存中Document的个数
-
maxFieldLength 这个是控制Field的分词后的大小的,因为一个Field分词后的值都是暂存到内存中,直到它写入tii和tis.所以可能大量的消耗内存,可以通过这个maxFieldLength来限制存放于中的词条个数.多余的词条将被忽略.
查询相关的类
- TermQuery基本的查询.
IndexSearcher searcher = new IndexSearcher(indexPath); Term t = new Term("name","张"); Query q = new TermQuery(t); Hits hits = searcher.search(q);
- BooleanQuery布尔查询.
这里Occur有如下三个取值:Occur.MUST,Occur.MUST_NOT,Occur.SHOULDIndexSearcher searcher = new IndexSearcher(indexPath); Term t1 = new Term("name","张"); Term t2 = new Term("name","小"); BooleanQuery query = new BooleanQuery(); query.add(new TermQuery(t1),Occur.MUST); query.add(new TermQuery(t2),Occur.MUST); Hits hits = searcher.search(query);
Occur的各种组合含义:
1. must must 有A,并且还需要有B
2. must must_not 只能有A,并且不能出现B
3. must should 无意义,检索按照must字句检索
4. must_not should 无意义,减速按照must_not 和 must检索
5. must_not must_not 无意义.不返回任何值
6. should should A 或者 B 或者AB都有 - RangeQuery 范围查询
构造函数RangeQuery(lowerTerm,uperTerm,inclusive)
1.lowerTerm开始查找的范围
2.uperTerm结束查找的范围
3.inclusive是否是开闭区间IndexSearcher searcher = new IndexSearcher(indexPath); Term begin = new Term("id","10000"); Term end = new Term("id","99999"); RangeQuery query = new RangeQuery(begin,end,false); searcher.search(query);//不包括10000的id和99999的id
- PrefixQuery 前缀查找
IndexSearcher searcher = new IndexSearcher(indexPath); Term start = new Term("name","张"); PrefixQuery query = new PrefixQuery(start); searcher.search(query);
- PhraseQuery短语查找
IndexSearcher searcher = new IndexSearcher(indexPath); Term t1 = new Term("content","你"); Term t2 = new Term("content","好"); PhraseQuery query = new PhraseQuery(); query.add(t1); query.add(t2); searcher.search(query); //严格匹配"你好"这样的短语 query.setSlop(1); //这里设置坡度为一,有可能就会搜索出"你不好"之类的内容 searcher.search(query);
- MultiPhraseQuery多短语搜索
IndexSearcher searcher = new IndexSearcher(indexPath); Term t1 = new Term("content","你"); Term t2 = new Term("content","好"); Term t3 = new Term("content","吗"); MultiPhraseQuery query = new MultiPhraseQuery(); query.add(new Term[] { t1,t2 }); query.add(t3); searcher.search(query); //这个可能会搜索出"你吗","好吗"这样的组合
- FuzzyQuery模糊搜索
FuzzyQuery query = new FuzzyQuery(term,minimumSimilartiy,prefixLength);
构造函数中,term代表搜索的词条,minimumSimiartiy代表搜索的模糊度,prefixLength表示结果需要匹配term的前面几个长度.换句话说,也就是搜索出来的内容,不管模糊度怎么样,前面prefixLength位长度的字符必须和term前面prefixLength位长度匹配.IndexSearcher searcher = new IndexSearcher(indexPath); Term t1 = new Term("content","book"); FuzzyQuery query = new FuzzyQuery(t1); searcher.search(query); //这个可能会搜索出"boot,cook"等之类的内容
- WildcardQuery通配符搜索
*代表多个字符 ?代表一个匹配字符IndexSearcher searcher = new IndexSearcher(indexPath); Term t1 = new Term("content","?oo*"); WildcardQuery query = new WildcardQuery(t1); searcher.search(query); //这个可能会搜索出"boot,tool"等之类的内容
- SpanQuery 跨度搜索
所谓跨度搜索就是词条和词条见的跨度.比如 I love you 那么I,love,you可能就是三个词条,那么搜索you的时候和正文首的跨度为2. I 和you之间的跨度为1.SpanQuery只是一个抽象类.所有的跨度搜索都是这个类的子类.
1. SpanTermQuery
2. SpanFirstQuery
3. SpanNearQuery
4. SpanOrQuery
5. SpanNotQuery
具体实例自己翻资料 - RegeQuery 正则搜索
这个是个第三方搜索类.用一个正则表达式进行搜索.具体实例自己翻资料 - QueryParser可以通过一个字符串自动构建Query对象。
默认情况下QueryParser对于字符串是进行的或操作.也就是should should操作(Boolean Query).如果想改变默认情况为与的关系,则需要执行这个方法:parser.setDefaultOperator(Operator.AND)
在解析的过程中如果字符串带有以下字符,则做相应的转换:
1. AND转义成BooleanQuery的与关系
2. OR转义成BooleanQuery的或关系
3. - 或 NOT不包括的内容,转义成BooleanQuery非关系
4. “ ” 引号扩上的字符串作为一个词条处理
5. ~ 针对于短语来说,这个符号代表坡度的意思 比如:”hello, hao ary you”~1
6. ~ 针对于模糊搜索,这个代表的是模糊度
7. ? 或 * 代表通配符
8. fieldName:张三 这样带冒号的,代表是指定在fieldName字段搜索
9. [xxx TO xxx] 这个转移成范围搜索
- MultiFieldQueryParser 多字段搜索
//多个字段中搜索一个内容 parse(String query,String[] fields,Analyzer analyzer); //多个字段中,搜索不同的内容 parse(String[] queries,String[] fields, Analyzer analyzer); //多个字段中,搜索不同的内容并指定关系 parse(String[] queries,String[] field,Occur[] flags,Analyzer analyzer);
- MultiSearcher多个索引上搜索的
IndexSearcher searcher1 = new IndexSearcher("path1"); IndexSearcher searcher2 = new IndexSearcher("path2"); MultiSearcher searcher = new MultiSearcher( new Searchable[] { searcher1,searcher2 });
- ParalellMultiSearcher多线程搜索,用法和MultiSearcher类似
评分标准
原理很复杂,运用到向量空间.实际开发中只需要知道如何操作评分即可.
如果正文越短,那么得分也会相应提高.
Field.setBoost(boost:float)激励因子,这个值越大,相对评分越高.但是不能是1.也不能为0。
IndexSearcher.explain(Query,int)查询得分和得分的计算公式.
其实这个是很早就总结过的了,但是项目中同样遇到很多问题,但是没有记录下来,以后有空时我会陆续添加到这里.