2012-03-09 68 views
1

还有就是得分的通配符匹配和精确匹配还有就是得分的通配符匹配和精确匹配之间的不匹配

我搜索

recording:live OR recording:luve* 

这里是之间的不匹配从搜索

DocNo:0:1.4196585:11111111-1cf0-4d1f-aca7-2a6f89e34b36 
1.4196585 = (MATCH) max plus 0.1 times others of: 
    0.3763506 = (MATCH) ConstantScore(recording:luve*), product of: 
    1.0 = boost 
    0.3763506 = queryNorm 
    1.3820235 = (MATCH) weight(recording:luve in 0), product of: 
    0.7211972 = queryWeight(recording:luve), product of: 
     1.9162908 = idf(docFreq=1, maxDocs=5) 
     0.3763506 = queryNorm 
    1.9162908 = (MATCH) fieldWeight(recording:luve in 0), product of: 
     1.0 = tf(termFreq(recording:luve)=1) 
     1.9162908 = idf(docFreq=1, maxDocs=5) 
     1.0 = fieldNorm(field=recording, doc=0) 

DocNo:1:0.3763506:22222222-1cf0-4d1f-aca7-2a6f89e34b36 
0.3763506 = (MATCH) max plus 0.1 times others of: 
    0.3763506 = (MATCH) ConstantScore(recording:luve*), product of: 
    1.0 = boost 
    0.3763506 = queryNorm 

在我的测试解释输出我有5个文件,一个包含完全匹配,另一个通配符匹配和其他三个不匹配所有。完全匹配的分数是1.40.37相比较为通配符匹配,这几乎是因子。与通配符搜索相比,对于罕见术语的精确匹配得分更高的指数要大得多。

完全不同是由于通配符用于精确匹配的不同得分机制,通配符不考虑tf/idf或lengthnorm考虑到你只是得到每个比赛的恒定得分。现在我不关心数据域中的长度或长度,它没有太大的区别,但分数是一个真正的杀手。由于匹配文档在5个文件一旦发现其基金的捐款是IDF的平方即3.61

我知道这个常数得分比计算TF-IDF更快* lengthnorm每个通配符匹配,但它没有任何意义对我来说,idf会为比分贡献很多。我也知道我可以改变重写方法,但是这有两个问题。

  1. 评分重写方法表现不佳,因为他们正在计算idf,tf和lengthnorm。 idf是我需要的唯一值。

  2. 确实计算分数的人没有多大意义,因为他们会计算匹配项的idf,即使这不是实际搜索的内容,而且该术语可能比我实际搜索的内容更罕见,可能会提升它高于完全匹配。

(我也可以改变相似性类别覆盖IDF计算所以它总是返回1,但由于以色列国防军是完全匹配比较不同的词

即是非常有用的,它没有任何意义录音:爱人或录音:爱人*或记录:在或录音:将*

我希望比赛以爱人得分超过匹配更高的常用词

因此,重写方法已经存在或可能只是为了计算它试图匹配的术语的idf,所以例如在这种情况下,我搜索'luve'和通配符匹配'luvely',它会由luve的idf(3.61)倍增。这样我的通配符匹配就可以完全匹配,我可以改变我的查询来提高精确匹配,所以精确匹配总是高于通配符匹配,但不会高得多。

i。È

recording:live^1.2 OR recording:luve* 

,并用这个神话重写方法这将给出(取决于queryNorm):

  • 文档0:0:1.692
  • 文件1:0:1.419
+0

你真的需要通配符? Uwe(Lucene提交者)说:“有一个简单的Lucene规则:当你需要通配符思考你的分析时,你可能做错了什么” – jpountz 2012-03-09 10:53:55

+0

当我说通配符时,它实际上是一个前缀查询(所以只是通配符结束)我确实需要从用户界面输入“uve”,但他们希望能够从他们输入的内容开始寻找单词。 – 2012-03-09 11:06:12

回答

0

好吧设置以此为前缀的查询重写方法似乎工作

public static class MultiTermUseIdfOfSearchTerm<Q extends Query> extends TopTermsRewrite<BooleanQuery> { 

    //public static final class MultiTermUseIdfOfSearchTerm extends TopTermsRewrite<BooleanQuery> { 
     private final Similarity similarity; 

     /** 
     * Create a TopTermsScoringBooleanQueryRewrite for 
     * at most <code>size</code> terms. 
     * <p> 
     * NOTE: if {@link BooleanQuery#getMaxClauseCount} is smaller than 
     * <code>size</code>, then it will be used instead. 
     */ 
     public MultiTermUseIdfOfSearchTerm(int size) { 
      super(size); 
      this.similarity = new DefaultSimilarity(); 

     } 

     @Override 
     protected int getMaxSize() { 
      return BooleanQuery.getMaxClauseCount(); 
     } 

     @Override 
     protected BooleanQuery getTopLevelQuery() { 
      return new BooleanQuery(true); 
     } 

     @Override 
     protected void addClause(BooleanQuery topLevel, Term term, float boost) { 
      final Query tq = new ConstantScoreQuery(new TermQuery(term)); 
      tq.setBoost(boost); 
      topLevel.add(tq, BooleanClause.Occur.SHOULD); 
     } 

     protected float getQueryBoost(final IndexReader reader, final MultiTermQuery query) 
       throws IOException { 
      float idf = 1f; 
      float df; 
      if (query instanceof PrefixQuery) 
      { 
       PrefixQuery fq = (PrefixQuery) query; 
       df = reader.docFreq(fq.getPrefix()); 
       if(df>=1) 
       { 
        idf = (float)Math.pow(similarity.idf((int) df, reader.numDocs()),2); 
       } 
      } 
      return idf; 
     } 

     @Override 
     public BooleanQuery rewrite(final IndexReader reader, final MultiTermQuery query) throws IOException { 
      BooleanQuery bq = (BooleanQuery)super.rewrite(reader, query); 

      float idfBoost = getQueryBoost(reader, query); 
      Iterator<BooleanClause> iterator = bq.iterator(); 
      while(iterator.hasNext()) 
      { 
       BooleanClause next = iterator.next(); 
       next.getQuery().setBoost(next.getQuery().getBoost() * idfBoost); 
      } 
      return bq; 
     } 

    } 
0
+0

不,不幸的是,患有上述问题2。如果uvely是一个很罕见的术语,那么包含ululy的文档可能会比luve更高,即使我们正在寻找luve – 2012-03-09 11:13:00

+0

您仍然可以使用布尔查询,其中一个确切的子句具有较高的提升,一个通配符子句具有较低的提升:'录音:luve^10录音:luve *' – jpountz 2012-03-09 13:37:16

+0

这并不能一直解决问题,因为当两个词的idf类似时,精确匹配将是wildcardmatch的十倍,但是当通配符有更好的idf那么结果会更近。所以它会在某些情况下运行良好,但在其他情况下运行良好 – 2012-03-09 13:58:52