`
Tonyguxu
  • 浏览: 278477 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【Lucene】查询term后加上'*'对打分的影响

 
阅读更多

 


 

 

 

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:

 

 写道
query=1065800715*
1.0 = (MATCH) ConstantScore(content:1065800715*), product of:
    1.0 = boost
    1.0 = queryNorm
 

 

 

 写道
query=1065800715* OR 106580071517
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继承结构


 

 

  • 大小: 41.7 KB
  • 大小: 17.8 KB
  • 大小: 90.2 KB
  • 大小: 10.5 KB
  • 大小: 24.3 KB
分享到:
评论

相关推荐

    Lucene+3.0+原理与代码分析完整版

    4. **影响 Lucene 对文档打分的因素**:包括词条频率、文档频率、文档长度、词条位置等。 5. **TooManyClause 异常**:当查询包含过多的子查询时,Lucene 会抛出 TooManyClauses 异常,以防止内存溢出等问题。 6. ...

    lucene的查询语法事例

    **Lucene查询语法详解** Apache Lucene是一款高性能、全文本搜索库,被广泛应用于各种搜索引擎的构建。在使用Lucene进行信息检索时,理解和掌握其查询语法至关重要。本篇文章将深入探讨Lucene的查询语法,帮助你更...

    Lucene in Action, Second Edition

    Lucene允许用户自定义索引分析器、相似度计算模型等关键组件,这意味着开发者可以根据特定的需求对Lucene进行扩展和修改。这种高度的灵活性使得Lucene成为构建定制化搜索解决方案的理想选择。 **7. Lucene的性能...

    Lucene in Action

    - **评分与排序**: 根据相关性对结果进行评分并排序。 - **结果返回**: 返回前 N 条最相关的记录。 - **索引优化技术**: - **合并**: 减少索引文件数量以提高性能。 - **缓存**: 加快检索速度。 - **分片**: 对...

    lucene-core-2.9.4,lucene-core-3.0.2,lucene-core-3.0.3,lucene-core-3.4.0

    - **查询执行优化**:3.4.0版本对查询执行引擎进行了重大优化,包括更快的评分计算和更高效的查询缓存。 - **N-gram支持**:增加了对N-gram查询的支持,提高了模糊搜索的性能。 - **倒排索引压缩**:引入了新的倒...

    Lucene3.0之查询类型详解

    【Lucene3.0查询类型详解】 在Lucene3.0中,查询处理是一个关键环节,涉及多种查询方式和理论模型。以下是对这些概念的详细解释: 1. **查询方式**: - **顺序查询**:是最简单的查询方式,直接遍历索引,效率较...

    Lucene 7.2.1 官方jar包

    - **术语(Term)**: 经过分析后的单词称为术语,是构建索引的基本元素。 ### 2. Lucene的主要组件 - **Analyzer**: 分析器负责文本的预处理,包括分词、去除标点符号、大小写转换等。 - **IndexWriter**: 负责...

    全文检索引擎Lucene

    3. **评分(Scoring)**: Lucene使用TF-IDF(Term Frequency-Inverse Document Frequency)算法对匹配文档进行评分,得分越高,相关性越强。 4. **排序和显示结果(Sorting and Displaying)**: 搜索结果按照评分...

    Lucene.net学习帮助文档

    除了基本的搜索功能,Lucene.net还提供了如高亮显示搜索结果、地理位置搜索、评分排序等功能。开发者可以根据需求通过扩展Lucene.net的功能来满足特定场景的应用。 **七、实战案例** 学习文档中可能包含了一些实际...

    Lucene的原理完整版pdf

    5. **术语(Term)**:经过分词后的单个词或短语称为术语,是Lucene搜索的基本单位。 ### 二、Lucene工作流程 1. **创建索引**:首先,开发者需要创建一个`IndexWriter`实例,然后调用`addDocument()`方法添加文档...

    lucene源码

    在源码中,`org.apache.lucene.index` 包下包含了许多类,如 `SegmentReader`, `Term`, `TermInfo`, `Field`, `Document` 等,用于处理索引的相关操作。 - **查询解析**:用户输入的查询字符串需要被解析成 Lucene ...

    lucene-2.4.0.rar

    - **TermVector支持**:2.4.0版引入了TermVector,可以存储每个文档中词汇的位置信息,有助于实现更精确的相关性评分。 3. **使用Lucene进行搜索引擎开发** - **索引创建**:首先,需要使用IndexWriter将文档内容...

    Lucene全文检索引擎

    7. **评分(Scoring)**:Lucene会根据文档与查询的相关性来为搜索结果打分,最相关的文档会首先返回。 **二、Lucene的工作流程** 1. **创建索引**:首先,你需要创建一个Analyzer来定义如何分词,然后使用...

    lucene示例 demo+jar包

    1. **索引(Indexing)**: Lucene 首先需要对数据进行索引,这个过程会将文本数据转换为倒排索引结构。倒排索引允许快速查找包含特定单词或短语的文档。 2. **文档(Documents)**: 在 Lucene 中,文档是搜索的基本...

    Lucene.net搜索

    3. **搜索索引**:用户输入查询后,Lucene.NET 将查询字符串转化为一系列的术语,然后在索引中查找匹配的文档。搜索结果根据相关性排序,返回给用户。 4. **结果展示**:根据搜索结果,用户可以看到匹配的文档列表...

    Lucene技术文档doc

    3. **文档检索**:根据查询结果,Lucene能够快速返回与查询相关的文档列表,同时提供相关度评分。 4. **排序与高亮**:Lucene不仅可以返回匹配的文档,还能根据相关度进行排序,并对匹配的查询词汇进行高亮显示。 *...

    lucene_jar包

    4. 高级特性:Lucene还提供了如布尔查询、短语查询、模糊查询、范围查询等多种查询方式,以及评分机制、过滤器、聚合等功能,可以满足复杂的搜索需求。 **4. 应用场景** Lucene广泛应用于网站搜索引擎、企业内部...

    Lucene3.0全文信息检索

    4. **结果排序**:根据查询相关性对结果进行排序,一般基于Term Frequency-Inverse Document Frequency (TF-IDF)算法。 5. **结果展示**:将搜索结果呈现给用户,包括文档摘要、评分等信息。 通过上述步骤,开发者...

    Lucene分词与查询详解

    5. **评分(Scoring)**:Lucene会根据查询和文档的相关性给出一个分数,决定搜索结果的排序。TF-IDF(Term Frequency-Inverse Document Frequency)是最常用的评分算法。 现在,我们详细讲解如何在Lucene中进行...

Global site tag (gtag.js) - Google Analytics