2012-02-13 65 views
16

如果我在Solr中有一个带有多值字段的文档,那么多个值是独立得分还是只是连在一起并且作为一个大字段打分?我希望他们独立得分。这里是我的意思的一个例子:solr多值字段的得分

我有一个字段的人的名字,其中可能有多个同名人的名字的文件。名字都是不同的(在某些情况下有很大的不同),但它们都是同一个人/文档。

人1: 大卫·鲍伊,大卫·罗伯特·琼斯,齐吉星尘,薄白公爵

人2: 大卫·莱特曼

人3: 大卫·哈塞尔霍夫,大卫·迈克尔·哈塞尔霍夫

如果我要搜索“大卫”,我希望所有这些人都有相同的比赛机会。如果每个名字独立得分,看起来就是这样。如果他们只是作为一个单独的领域进行存储和搜索,David Bowie将因为拥有更多的令牌而受到惩罚。 Solr如何处理这种情况?

回答

18

你可以运行你的查询q=field_name:DaviddebugQuery=on看看会发生什么。

这些结果(包括通过fl=*,score分数)由score desc排序:

<doc> 
    <float name="score">0.4451987</float> 
    <str name="id">2</str> 
    <arr name="text_ws"> 
     <str>David Letterman</str> 
    </arr> 
</doc> 
<doc> 
    <float name="score">0.44072422</float> 
    <str name="id">3</str> 
    <arr name="text_ws"> 
     <str>David Hasselhoff</str> 
     <str>David Michael Hasselhoff</str> 
    </arr> 
</doc> 
<doc> 
    <float name="score">0.314803</float> 
    <str name="id">1</str> 
    <arr name="text_ws"> 
     <str>David Bowie</str> 
     <str>David Robert Jones</str> 
     <str>Ziggy Stardust</str> 
     <str>Thin White Duke</str> 
    </arr> 
</doc> 

而且这样的解释:

<lst name="explain"> 
    <str name="2"> 
     0.4451987 = (MATCH) fieldWeight(text_ws:David in 1), product of: 1.0 = tf(termFreq(text_ws:David)=1) 0.71231794 = idf(docFreq=3, maxDocs=3) 0.625 = fieldNorm(field=text_ws, doc=1) 
    </str> 
    <str name="3"> 
     0.44072422 = (MATCH) fieldWeight(text_ws:David in 2), product of: 1.4142135 = tf(termFreq(text_ws:David)=2) 0.71231794 = idf(docFreq=3, maxDocs=3) 0.4375 = fieldNorm(field=text_ws, doc=2) 
    </str> 
    <str name="1"> 
     0.314803 = (MATCH) fieldWeight(text_ws:David in 0), product of: 1.4142135 = tf(termFreq(text_ws:David)=2) 0.71231794 = idf(docFreq=3, maxDocs=3) 0.3125 = fieldNorm(field=text_ws, doc=0) 
    </str> 
</lst> 

的评分这里的因素是:

  • termFreq:howt连接一个词出现在文档中
  • IDF:术语出现的频率在整个指数
  • fieldNorm:术语的重要性,这取决于指数时间提高和字段长度

在你的例子fieldNorm会有所作为。由于该字段只出现一次,因此您有一个文档的更低的termFreq(1而不是1.4142135),但由于字段长度的原因该匹配更重要。

您的字段是多值的事实不会改变评分。我想这与内容相同的单个值域相同。 Solr根据字段长度和术语工作,所以,是的,David Bowie因为拥有比其他许多令牌而受到惩罚。 :)

UPDATE
其实,我觉得大卫·鲍伊值得他的机会。像上面解释的那样,fieldNorm是有差别的。将属性omitNorms=true添加到您的text_ws字段中的schema.xml和reindex。同样的查询会给你以下结果:

<doc> 
    <float name="score">1.0073696</float> 
    <str name="id">1</str> 
    <arr name="text"> 
     <str>David Bowie</str> 
     <str>David Robert Jones</str> 
     <str>Ziggy Stardust</str> 
     <str>Thin White Duke</str> 
    </arr> 
</doc> 
<doc> 
    <float name="score">1.0073696</float> 
    <str name="id">3</str> 
    <arr name="text"> 
     <str>David Hasselhoff</str> 
     <str>David Michael Hasselhoff</str> 
    </arr> 
</doc> 
<doc> 
    <float name="score">0.71231794</float> 
    <str name="id">2</str> 
    <arr name="text"> 
     <str>David Letterman</str> 
    </arr> 
</doc> 

正如你可以看到现在的termFreq胜的fieldNorm没有考虑到的。这就是为什么包含两次大卫事件的两份文件尽管长度各不相同,但仍处于顶端并且得分相同,而只有一场比赛的较短文档是最后一次得分最低的文档。下面是与debugQuery=on的解释:

<lst name="explain"> 
    <str name="1"> 
     1.0073696 = (MATCH) fieldWeight(text:David in 0), product of: 1.4142135 = tf(termFreq(text:David)=2) 0.71231794 = idf(docFreq=3, maxDocs=3) 1.0 = fieldNorm(field=text, doc=0) 
    </str> 
    <str name="3"> 
     1.0073696 = (MATCH) fieldWeight(text:David in 2), product of: 1.4142135 = tf(termFreq(text:David)=2) 0.71231794 = idf(docFreq=3, maxDocs=3) 1.0 = fieldNorm(field=text, doc=2) 
    </str> 
    <str name="2"> 
     0.71231794 = (MATCH) fieldWeight(text:David in 1), product of: 1.0 = tf(termFreq(text:David)=1) 0.71231794 = idf(docFreq=3, maxDocs=3) 1.0 = fieldNorm(field=text, doc=1) 
    </str> 
</lst> 
+0

感谢您的详细分类,这正是我需要知道的。有没有另外一种方法可以将这些数据编入索引,让这些名称的评分更“公平”? – user605331 2012-02-13 15:02:46

+1

@ user605331看看我更新的答案,我也给了David Bowie一个机会! – javanna 2012-02-20 19:03:25

+1

省略规范有所帮助,但这不是一个好的解决方案。有人可能需要考虑fieldNorm,但仍然需要使用多值字段。所以我们必须在这两个之间做出决定:( – 2014-09-18 08:32:03

3

你可以使用Lucenes SweetSpotSimilarity定义的长度应该都有1.0的规范的平台。这可以帮助你处理你的情况,只要你正在寻找名字等东西。lengthNorm没有任何好处。

+0

这看起来很有希望。它被设置在IndexWriter级别,但不是针对特定字段,所以如果我有一个大的其他文本字段(可能是传记或者适合这里例子的东西),那么我将不得不为SweetSpotSimilarity使用它,对吗? – user605331 2012-02-15 16:29:52