- 浏览: 278477 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (161)
- 【**计划】 (2)
- 【**Core Java**】 (30)
- 【**JAVA EE】 (6)
- JDBC (3)
- Hibernate专题系列 (0)
- 【**OS】 (14)
- 【**架构设计/设计模式】 (11)
- 【Hadoop】 (3)
- 【**分布式】 (9)
- 模板 (1)
- C (2)
- 常用工具 (1)
- Oracle (2)
- 【Tips】 (3)
- 【数据库】 (2)
- 玩转Ubuntu (0)
- 【计算机网络/网络编程】 (7)
- 【**Search Engine】 (21)
- 【**专题**】 (6)
- 【**Python】 (10)
- XML (1)
- 【**Open Source Framework】 (1)
- 【高级主题】 (1)
- 【存储】 (3)
- 【笔试面试】 (2)
- 【**数据结构与算法设计】 (20)
- 【其他】 (3)
- 【编程练习】 (2)
- 【待完成】 (12)
- 【工作】 (6)
- 【软件研发】 (4)
- 【**多线程多进程编程】 (5)
- 【Web Service】 (1)
- 【表达式解析/JavaCC系列】 (5)
- 【缓存系统:Memcached】 (1)
- 【Java IO/NIO】 (5)
- 【JVM运行机制及内存管理】 (7)
最新评论
-
107x:
...
python list排序 -
yuzhu223:
...
【Python基础】Python的lambda函数与排序 -
Tonyguxu:
分析查询结果的打分小于11.query=1065800715* ...
lucene打分机制的研究 -
Tonyguxu:
query=139320661963.013709 = (MA ...
lucene打分机制的研究 -
Tonyguxu:
query=10658007150.6772446 = (MA ...
lucene打分机制的研究
BooleanWeight里sumOfSquaredWeights实现
@Override public float sumOfSquaredWeights() throws IOException { float sum = 0.0f; for (int i = 0 ; i < weights.size(); i++) { // call sumOfSquaredWeights for all clauses in case of side effects float s = weights.get(i).sumOfSquaredWeights(); // sum sub weights if (!clauses.get(i).isProhibited()) // only add to sum for non-prohibited clauses sum += s; } sum *= getBoost() * getBoost(); // boost each sub-weight return sum ; }
query=1065800715* OR 106580071517
在BooleanWeight里sumOfSquaredWeights打断点,查看值如下:
Weight对象树
》》》继续 《lucene原理与代码分析》p266
query=1065800715*
note:没有执行ConstantScoreQuery.sumOfSquaredWeights()、TermQuery.sumOfSquaredWeights()
====================分析=====================
对查询语句解析会生成一个Query对象树,
如Query query = queryParser.parse("+(+apple* -boy)(cat* dog)-(eat~ foods)");
在树的叶子节点中:
1.最基本的是TermQuery,表示一个词
2.还可以是PrefixQuery(前缀查询)、FuzzyQuery(模糊查询),这些查询语句由于特殊的语法,可能对应的不是一个词,而是多个词,在查询过程中会得到特殊处理。
PrefixQuery,比如 PrefixQuery("/usr/local")那么"/usr/local/a"、"/usr/local/b"都满足该前缀,term就有多个;
FuzzyQuery,用于匹配与指定term相似的term,如"three"和"tree";
在搜索过程中,会重写Query对象树,重写过程是一个递归过程,会一直处理到叶子节点。如果有子句被重写,则返回新的对象树,否则获得的是老的Query对象树。
为什么要对Query对象树重写(Query对象树重写是怎样一个过程)?
Query树的叶子节点基本是两种,或是TermQuery,或是MultiTermQuery(如上面提到的 PrefixQuery和 FuzzyQuery )。
MultiTermQuery继承结构如下:
TermQuery的重写方法返回对象本身,真正需要重写的是MultiTermQuery,也即一个Query代表多个Term参与查询。
重写过程如下:
首先,从索引文件的词典中,将多个Term都找出来,比如"appl*",可以从词典中找出如下Term:"apple","apples","apply",这些Term都要参与查询,而非原来的"appl*"参与查询过程,因为词典中是没有"appl*"。
然后,将取出的多个Term重新组织成新的Query对象进行查询(就是上面说的Query对象树重写),基本有两种方式:
方式1:将多个Term看成一个Term,即将包含它们的文档号取出来放在一起(Docid set),作为一个统一的倒排表参与倒排表的合并。——具体实现可以参看源码
对于方式1,多个Term,将包含Term的文档号放在一个docid set里,作为统一倒排表参与合并,这样多个Term之间的tf,idf的差别就会被忽略,所以采用方式一的RewriteMethod为CONSTANT_SCORE_XXX,也即除了用户指定的query boost(和 queryNorm )外,其他的因子不参与计算。
查看search的explanation:
1.0 = (MATCH) ConstantScore(content:1065800715*), product of:
1.0 = boost
1.0 = queryNorm
1.7799454 = (MATCH) sum of:
0.13035534 = (MATCH) ConstantScore(content:1065800715*), product of:
1.0 = boost
0.13035534 = queryNorm
1.64959 = (MATCH) weight(content:106580071517 in 900495), product of:
0.9914673 = queryWeight(content:106580071517), product of:
7.6058817 = idf(docFreq=14268, maxDocs=10550949)
0.13035534 = queryNorm
1.6637866 = (MATCH) fieldWeight(content:106580071517 in 900495), product of:
1.0 = tf(termFreq(content:106580071517)=1)
7.6058817 = idf(docFreq=14268, maxDocs=10550949)
0.21875 = fieldNorm(field=content, doc=900495)
至
0.06517767 = (MATCH) product of:
0.13035534 = (MATCH) sum of:
0.13035534 = (MATCH) ConstantScore(content:1065800715*), product of:
1.0 = boost
0.13035534 = queryNorm
0.5 = coord(1/2)
方式2:将多个Term组成一个BooleanQuery,这些Term之间是OR的关系。
对于 MultiTermQuery这种查询打分忽略tf-idf是合理的么?
Lucene认为对于 MultiTermQuery这种查询,打分忽略tf-idf是合理的。因为当用户输入"appl*"时,用户也不确切清楚索引中有什么与"appl*"相关,也就不偏爱其中之一,这样计算词之间的差别(tf-idf)对用户而言也就没有什么意义。
何时用方式一进行Query对象树重写?
如果Term数目超限,或者文档数目超限(在播发日志查询里,如查1065800715*就属于这种情况),采用的是方式一,这样能避免文档数目太多而使倒排表合并大的性能消耗。
方式一源码分析:
MultiTermQuery里
public static final RewriteMethod CONSTANT_SCORE_FILTER_REWRITE = new RewriteMethod() { @Override public Query rewrite(IndexReader reader, MultiTermQuery query) { Query result = new ConstantScoreQuery(new MultiTermQueryWrapperFilter<MultiTermQuery>(query)); result.setBoost(query.getBoost()); return result; } // Make sure we are still a singleton even after deserializing protected Object readResolve() { return CONSTANT_SCORE_FILTER_REWRITE; } };
MultiTermQueryWrapperFilter
/** * Returns a DocIdSet with documents that should be * permitted in search results. */ @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { //得到MutilTermQuery的Term枚举器 final TermEnum enumerator = query.getEnum(reader); try { // if current term in enum is null, the enum is empty -> shortcut if (enumerator.term() == null) return DocIdSet.EMPTY_DOCIDSET; // else fill into a FixedBitSet //创建包含多个Term的文档号集合 final FixedBitSet bitSet = new FixedBitSet(reader.maxDoc()); final int[] docs = new int[32]; final int[] freqs = new int[32]; TermDocs termDocs = reader.termDocs(); try { int termCount = 0; //每次循环,取出MutilTermQuery中的Term,取出还有该Term的所有文档号,加入集合中 do { Term term = enumerator.term(); if (term == null) break; termCount++; termDocs.seek(term); while (true) { final int count = termDocs.read(docs, freqs); if (count != 0) { for(int i=0;i<count;i++) { bitSet.set(docs[i]); } } else { break; } } } while (enumerator.next()); query.incTotalNumberOfTerms(termCount); } finally { termDocs.close(); } return bitSet; } finally { enumerator.close(); } }
附:
Lucene Query继承结构
发表评论
-
【Lucene】建索引核心类介绍
2012-06-08 17:28 1063IndexWriter 负责创建新索引或打开已有索引, ... -
优秀文章汇总
2012-05-08 18:48 771搜索引擎技术之概要预览 http://blog.csd ... -
【Lucene】lucene查询Query对象
2012-05-08 18:41 1417PrefixQuery 前缀查询。 如 test* 会匹配 ... -
【工作】日志检索结果的排序改进分析
2012-04-27 18:07 963下图是现在生产环境的部署图,索引文件分布在70-7 ... -
lucene.search.Weight
2012-04-25 15:39 995org.apache.lucene.search Cl ... -
lucene.search.Similarity
2012-04-20 10:31 2554Similarity defines the componen ... -
lucene打分机制的研究
2012-04-22 17:46 5861提出问题 目前在查询时,会将得分小于1的查询结果过滤掉。 ... -
tokenize和tokenizer到底怎么翻译?
2012-03-28 10:32 3577在编写词法分析器(Lexer)或语法分析器(Parse ... -
【Lucene】更合理地使用Document和Field
2012-03-27 09:39 5442writer = ...; //#1 Prepared ... -
【Lucene】构建索引
2012-03-17 23:16 762Lucene索引的过程是什么? step1 收集待 ... -
信息检索类小程序
2012-03-17 00:37 8471.对四大名著txt实现索引和搜索功能 2. -
【Lucene】Scoring
2012-03-13 23:47 1168http://lucene.apache.org/core/o ... -
Information Retrieval
2012-03-13 22:50 1003http://wiki.apache.org/lucene-j ... -
【Lucene】lucene的评分机制
2012-03-07 16:24 951测试环境里查询条件1065800714,为什么Score ... -
【Lucene】搜索的核心类简介
2012-03-05 18:48 1386注:Lucene版本为3.4 I ... -
【Lucene】How to make indexing faster
2012-02-16 14:54 838http://wiki.apache.org/lucene-j ... -
【Lucene】index包IndexWriter
2011-12-25 01:50 803Q1:IndexWriter作用是什么? Q2:索引过 ... -
【Lucene】store包SimpleFSDirectory
2011-12-24 23:43 806store包SimpleFSDirectory -
【Lucene】store包FSDirectory
2011-12-24 13:39 1437源码中涉及以下知识点: 1.java.security.Me ... -
【Lucene】store包Directory
2011-12-11 17:23 1321说明 lucene的版本是3.0.3 结构及类图 文件类 ...
相关推荐
4. **影响 Lucene 对文档打分的因素**:包括词条频率、文档频率、文档长度、词条位置等。 5. **TooManyClause 异常**:当查询包含过多的子查询时,Lucene 会抛出 TooManyClauses 异常,以防止内存溢出等问题。 6. ...
**Lucene查询语法详解** Apache Lucene是一款高性能、全文本搜索库,被广泛应用于各种搜索引擎的构建。在使用Lucene进行信息检索时,理解和掌握其查询语法至关重要。本篇文章将深入探讨Lucene的查询语法,帮助你更...
Lucene允许用户自定义索引分析器、相似度计算模型等关键组件,这意味着开发者可以根据特定的需求对Lucene进行扩展和修改。这种高度的灵活性使得Lucene成为构建定制化搜索解决方案的理想选择。 **7. Lucene的性能...
- **评分与排序**: 根据相关性对结果进行评分并排序。 - **结果返回**: 返回前 N 条最相关的记录。 - **索引优化技术**: - **合并**: 减少索引文件数量以提高性能。 - **缓存**: 加快检索速度。 - **分片**: 对...
- **查询执行优化**:3.4.0版本对查询执行引擎进行了重大优化,包括更快的评分计算和更高效的查询缓存。 - **N-gram支持**:增加了对N-gram查询的支持,提高了模糊搜索的性能。 - **倒排索引压缩**:引入了新的倒...
【Lucene3.0查询类型详解】 在Lucene3.0中,查询处理是一个关键环节,涉及多种查询方式和理论模型。以下是对这些概念的详细解释: 1. **查询方式**: - **顺序查询**:是最简单的查询方式,直接遍历索引,效率较...
- **术语(Term)**: 经过分析后的单词称为术语,是构建索引的基本元素。 ### 2. Lucene的主要组件 - **Analyzer**: 分析器负责文本的预处理,包括分词、去除标点符号、大小写转换等。 - **IndexWriter**: 负责...
3. **评分(Scoring)**: Lucene使用TF-IDF(Term Frequency-Inverse Document Frequency)算法对匹配文档进行评分,得分越高,相关性越强。 4. **排序和显示结果(Sorting and Displaying)**: 搜索结果按照评分...
除了基本的搜索功能,Lucene.net还提供了如高亮显示搜索结果、地理位置搜索、评分排序等功能。开发者可以根据需求通过扩展Lucene.net的功能来满足特定场景的应用。 **七、实战案例** 学习文档中可能包含了一些实际...
5. **术语(Term)**:经过分词后的单个词或短语称为术语,是Lucene搜索的基本单位。 ### 二、Lucene工作流程 1. **创建索引**:首先,开发者需要创建一个`IndexWriter`实例,然后调用`addDocument()`方法添加文档...
在源码中,`org.apache.lucene.index` 包下包含了许多类,如 `SegmentReader`, `Term`, `TermInfo`, `Field`, `Document` 等,用于处理索引的相关操作。 - **查询解析**:用户输入的查询字符串需要被解析成 Lucene ...
- **TermVector支持**:2.4.0版引入了TermVector,可以存储每个文档中词汇的位置信息,有助于实现更精确的相关性评分。 3. **使用Lucene进行搜索引擎开发** - **索引创建**:首先,需要使用IndexWriter将文档内容...
7. **评分(Scoring)**:Lucene会根据文档与查询的相关性来为搜索结果打分,最相关的文档会首先返回。 **二、Lucene的工作流程** 1. **创建索引**:首先,你需要创建一个Analyzer来定义如何分词,然后使用...
1. **索引(Indexing)**: Lucene 首先需要对数据进行索引,这个过程会将文本数据转换为倒排索引结构。倒排索引允许快速查找包含特定单词或短语的文档。 2. **文档(Documents)**: 在 Lucene 中,文档是搜索的基本...
3. **搜索索引**:用户输入查询后,Lucene.NET 将查询字符串转化为一系列的术语,然后在索引中查找匹配的文档。搜索结果根据相关性排序,返回给用户。 4. **结果展示**:根据搜索结果,用户可以看到匹配的文档列表...
3. **文档检索**:根据查询结果,Lucene能够快速返回与查询相关的文档列表,同时提供相关度评分。 4. **排序与高亮**:Lucene不仅可以返回匹配的文档,还能根据相关度进行排序,并对匹配的查询词汇进行高亮显示。 *...
4. 高级特性:Lucene还提供了如布尔查询、短语查询、模糊查询、范围查询等多种查询方式,以及评分机制、过滤器、聚合等功能,可以满足复杂的搜索需求。 **4. 应用场景** Lucene广泛应用于网站搜索引擎、企业内部...
4. **结果排序**:根据查询相关性对结果进行排序,一般基于Term Frequency-Inverse Document Frequency (TF-IDF)算法。 5. **结果展示**:将搜索结果呈现给用户,包括文档摘要、评分等信息。 通过上述步骤,开发者...
5. **评分(Scoring)**:Lucene会根据查询和文档的相关性给出一个分数,决定搜索结果的排序。TF-IDF(Term Frequency-Inverse Document Frequency)是最常用的评分算法。 现在,我们详细讲解如何在Lucene中进行...