Summary of Lucene In Action
Chapter 2
Chapter 2
这一章是关于Building a search index,主要要点如下
- Document是index和searcher的基本单元,比如IndexWriter就提供了addDocument的API,它们是直接跟Document打交道,而Field是已经封装在Document里面了。所以任何东西要是想用Lucene来索引,都要先转化成Document+Field的model。
- 一个Index的过程包含这么几个步骤:1)extracting and creating the document,比如html文档需要先把一些没有用的tag去除掉 2) Analysis, 对应的output是a stream of tokens,中间可以加各种Filter,比如LowerCaseFilter, StopFilter 3)把token stream加到inverted index里面
- Boosting是让不同的document或者不同的Field具有不同的权重,比如PageRank也是一种boosting的形式,来自wikipedia的网页的权重就比其它网站的要高。boosting可以在index的时候设置,也可以在search的时候动态设置。Document和Field都有一个setBoost函数。
- 要对数字,日期,时间进行索引的话,用NumericField
- IndexWriter可以通过MaxFieldLength来限制field对应的value的长度,好处是可以避免一些格外长的document加到index里头(比如一个很大的binary文件错以为是text文件进行索引,会产生大量很奇怪的token)
- Lucene删除文档,只是维护一个bit array,然后把对应位置0而已,并没有在磁盘真的把那个document删掉,因为就算删掉了,那点磁盘空间也很难重新利用了。
- Flush可以由三种方式来触发: 1)占用多少内存 2)添加了多少文档 3)多少个term被删除,每次flush都会生成一个新的segment,在commit之前,这些新建的segment等信息对Reader是不可见的
- MergePolicy决定什么时候执行一次merge
这样主要讲的是如何支持基本的搜索
- It is crucial that the terms passed to IndexSearcher be consistent with the terms produced by analysis of the source documents during indexing.
- Lucene的socring function为
- 自定义的Scoring Function是继承Similarity类
- IndexSearcher有explain函数,可以看到每一个document的score的组成,比如可以告诉你某个document的tf, idf多少
- 搜索包含某个词的文档用TermQuery
- 搜索包含某个范围的term用TermRangeQuery,比如搜索标题的首字母是从d到j的任何一个字符
- 搜索某个field落在给定范围里头的文档用NumericRangeQuery,比如价格在100-200的hotel
- 搜索包含关键词里面包含某个prefix的文档用PrefixQuery,比如搜索category包含前缀/technology/computers/programming的所有文档
- BooleanQuery可以实现AND,OR,NOT等逻辑
- 词组的搜索用PhraseQuery
- 通用符的搜索用WildcardQuery
- 关键词的近似搜索(edit distance)用FuzzyQuery
- 返回index的所有document用MatchAllDocsQuery
- QueryParser提供了更为通用的方式来方便用户定制自己需要的query,上面提到的几种Query相当于封装好的模板
- QueryParser里头的转义字符有\ + – ! ( ) : ^ ] { } ~ *
这章讲的是Lucene的Analyzer
- Analyzer做的事情是把text变成一堆term,比如”XY&Z Corporation – xyz@example.com”通过Lucene的StandardAnalyzer就识别成3个term: [XY&Z] [Corporation]和[xyz@example.com]
- Document的Field如果设置Analyzed,就会对text部分进行分析,拆解成一堆term(tokens),否则就整个text部分当作一个term
- Tokenizer用的是装饰模式,可以嵌套一堆的TokenFilter,来实现功能的叠加
- 当text变成一堆token的时候,offset表示某个token在原来text的出现位置(按字符数计算),而position是这个token在原来的text里面属于第几个token
- Token还可以有类型,比如ALPHANUM,EMAIL
- TokenFilter叠加的顺序不同,产生的结果可能也不同
- 常见的内嵌的Analyzer有WhitespaceAnalyzer(拿空白符来分词),SimpleAnalyzer(拿非英文字母来分词,并且转小写),StopAnalyzer(SimpleAnalyzer加去除stop word的功能),KeywordAnalyzer(整个text当作一个token), StandardAnalyzer(比较复杂,可以识别email,地址,中文日文等)
- FieldCache可以把所有document在某个field上面的值都load到memory里头,返回的是一个数组,长度是所有document的数目,也就是说如果某个document没有这个field,也会有一个默认值
- Searcher的search函数可以指定filter和score,一般会先执行filter,然后再对剩下的结果排序。要按照relevance排序,用Sort.RELEVANCE,要按照index order(即document id)排序用Sort.INDEXORDER,要按照某个field排序用new SortField(“fieldname”, SortField.String/Int等),如果要反向排序,可以设置第三个参数为true
- 如果要按照多个field排序(当某个field的值一样的时候就按照下一个field来排序)可以这样子
- Searcher的search函数可以指定filter和score,一般会先执行filter,然后再对剩下的结果排序。要按照relevance排序,用Sort.RELEVANCE,要按照index order(即document id)排序用Sort.INDEXORDER,要按照某个field排序用new SortField(“fieldname”, SortField.String/Int等),如果要反向排序,可以设置第三个参数为true
- 相比PhraseQuery,SpanQuery可以更加灵活地指定搜索的关键词在文档里面的位置是否足够靠近。以”the quick brown fox jumps over the lazy dog”为例,SpanFirstQuery是判断一个term离开头的位置是不是在某个范围里面,比如(brown, 2)就不是一个match,而(brown, 3)是一个match,SpanNearQuery是判断几个term互相的距离是不是在某个范围里面。SpanOrQuery是把几个SpanQuery的结果整合起来。
- 常见的Filter有, TermRangeFilter (按document是否包含某个范围的term),NumericRangeFilter(document的field必须在某个range里头), FieldCacheRangeFilter(类似NumericRangeFilter,只是用了FieldCache),FieldCacheTermsFilter(类似TermRangeFilter,只是用了FieldCache),SpanQueryFilter(类似SpanQuery,只是没有scoring), PrefixFilter(类似PrefixQuery,只是没有scoring),FilteredDocIdSet可以自定义一个document id是否匹配)
- 在多个Directory里面进行搜索,然后把各自的搜索结果合并,用MultiSearcher,如果需要多线程,让每一个线程搜索一个Directory,用ParallelMultiSearcher
- term vector是记录一个document里面有哪些term,可以用于document similarity search, categorizing documents
- 当load整个document的代价比较大,而且最后结果的显示也不需要整个document的时候,可以用FieldSelector,使用的时候记得考虑磁盘指针load完一个field,跳到下一个要load的field的时候也是有代价的。
- 前面提到的scoring主要是基于relevance, doc id, field来排序,如果要实现更高级的,可以继承FieldComparatorSource,举了一个spatial documents按照离query point的距离排序的例子
- Collector是收集Scorer的中间结果
- QueryParser也是可以继承并加以扩展的,举了一个如何解析”price:[10 TO 20]“的例子
- Payloads允许每一个term在index的时候可以存储一个任意长度的byte数组,Lucene的index和searcher并不关心里面存的是什么内容
- 关于file format可以参考 http://lucene.apache.org/core/3_6_2/fileformats.html
No comments:
Post a Comment