我目前正在研究轮胎 gem (我对Elasticsearch和lucene还是陌生的),并尝试了一些方法。我将需要进行一些(可能是不平凡的)计分,所以我会设法捕获这一点。我阅读了在网上可以找到的有关计分公式的所有内容,并尝试将我找到的内容与解释的查询进行匹配。
如果我正确阅读这些数字,则标题为“foo foo foo foo foo”的文档的分数会有所不同,这肯定不是预期的。我想我在索引编制过程中或之后都缺少一个步骤,但是我无法弄清楚。
下面是我的代码。我并没有完全按照轮胎DSL的预期方式进行,因为我想弄清楚-某些时候以后看起来可能更疲倦。
require 'tire'
require 'pp'
class Model
INDEX = 'myindex'
TYPE = 'company'
class << self
def delete_index
Tire.index(INDEX) { delete }
end
def create_mapping
Tire.index INDEX do
create mappings: {
TYPE => {
properties: {
title: { type: 'string' }
}
}
}
end
end
def refresh_index
Tire.index INDEX do
refresh
end
end
end
def initialize(attributes = {})
@attributes = attributes.merge(:_id => object_id) #use oid as id, just for testing
end
def _type
TYPE
end
def id
object_id.to_s #convert to string because tire compares to object_id!
end
def index
item = self
Tire.index INDEX do
store item
end
end
def to_indexed_json
@attributes.to_json
end
ENTITIES = [
new(title: "foo foo foo foo"),
new(title: "foo"),
new(title: "bar"),
new(title: "foo bar"),
new(title: "xxx"),
new(title: "foo foo foo foo"),
new(title: "foo foo"),
new(title: "foo bar baz")
]
QUERIES = {
:foo => { query_string: { query: "foo" } },
:all => { match_all: {} }
}
def self.custom_explained_search(q)
Tire.search(Model::INDEX, :wrapper => Model, :explain => true) do |search|
search.query do |query|
query.send :instance_variable_set, :@value, q
end
end
end
end
class Tire::Results::Collection
def explained
@response["hits"]["hits"].map do |hit|
{
"_id" => hit["_id"],
"_explanation" => hit["_explanation"],
"title" => hit["_source"]["title"]
}
end
end
end
Model.delete_index
Model.create_mapping
Model::ENTITIES.each &:index
Model.refresh_index
s = Model.custom_explained_search(Model::QUERIES[:foo])
pp s.results.explained
打印结果是这样的:
[{"_id"=>"2169251840",
"_explanation"=>
{"value"=>0.54932046,
"description"=>"fieldWeight(_all:foo in 0), product of:",
"details"=>
[{"value"=>1.4142135,
"description"=>"btq, product of:",
"details"=>
[{"value"=>1.4142135, "description"=>"tf(phraseFreq=2.0)"},
{"value"=>1.0, "description"=>"allPayload(...)"}]},
{"value"=>0.7768564, "description"=>"idf(_all: foo=4)"},
{"value"=>0.5, "description"=>"fieldNorm(field=_all, doc=0)"}]},
"title"=>"foo foo foo foo"},
{"_id"=>"2169251720",
"_explanation"=>
{"value"=>0.54932046,
"description"=>"fieldWeight(_all:foo in 1), product of:",
"details"=>
[{"value"=>0.70710677,
"description"=>"btq, product of:",
"details"=>
[{"value"=>0.70710677, "description"=>"tf(phraseFreq=0.5)"},
{"value"=>1.0, "description"=>"allPayload(...)"}]},
{"value"=>0.7768564, "description"=>"idf(_all: foo=4)"},
{"value"=>1.0, "description"=>"fieldNorm(field=_all, doc=1)"}]},
"title"=>"foo"},
{"_id"=>"2169250520",
"_explanation"=>
{"value"=>0.48553526,
"description"=>"fieldWeight(_all:foo in 2), product of:",
"details"=>
[{"value"=>1.0,
"description"=>"btq, product of:",
"details"=>
[{"value"=>1.0, "description"=>"tf(phraseFreq=1.0)"},
{"value"=>1.0, "description"=>"allPayload(...)"}]},
{"value"=>0.7768564, "description"=>"idf(_all: foo=4)"},
{"value"=>0.625, "description"=>"fieldNorm(field=_all, doc=2)"}]},
"title"=>"foo foo"},
{"_id"=>"2169251320",
"_explanation"=>
{"value"=>0.44194174,
"description"=>"fieldWeight(_all:foo in 1), product of:",
"details"=>
[{"value"=>0.70710677,
"description"=>"btq, product of:",
"details"=>
[{"value"=>0.70710677, "description"=>"tf(phraseFreq=0.5)"},
{"value"=>1.0, "description"=>"allPayload(...)"}]},
{"value"=>1.0, "description"=>"idf(_all: foo=1)"},
{"value"=>0.625, "description"=>"fieldNorm(field=_all, doc=1)"}]},
"title"=>"foo bar"},
{"_id"=>"2169250380",
"_explanation"=>
{"value"=>0.27466023,
"description"=>"fieldWeight(_all:foo in 3), product of:",
"details"=>
[{"value"=>0.70710677,
"description"=>"btq, product of:",
"details"=>
[{"value"=>0.70710677, "description"=>"tf(phraseFreq=0.5)"},
{"value"=>1.0, "description"=>"allPayload(...)"}]},
{"value"=>0.7768564, "description"=>"idf(_all: foo=4)"},
{"value"=>0.5, "description"=>"fieldNorm(field=_all, doc=3)"}]},
"title"=>"foo bar baz"},
{"_id"=>"2169250660",
"_explanation"=>
{"value"=>0.2169777,
"description"=>"fieldWeight(_all:foo in 0), product of:",
"details"=>
[{"value"=>1.4142135,
"description"=>"btq, product of:",
"details"=>
[{"value"=>1.4142135, "description"=>"tf(phraseFreq=2.0)"},
{"value"=>1.0, "description"=>"allPayload(...)"}]},
{"value"=>0.30685282, "description"=>"idf(_all: foo=1)"},
{"value"=>0.5, "description"=>"fieldNorm(field=_all, doc=0)"}]},
"title"=>"foo foo foo foo"}]
我读错数字了吗?还是滥用轮胎?也许只是缺少一些“重新索引整个馆藏”步骤?
最佳答案
afaik如果未定义显式排序字段,则排序默认为tf * idf(http://en.wikipedia.org/wiki/Tf * idf)的变体。
从字面上看:术语频率*反文档频率。
从维基百科:
术语频率(术语计数):给定文档中的术语计数只是给定术语在该文档中出现的次数
反向文档频率用于衡量该术语在所有文档中是通用还是罕见。通过将文档总数除以包含该术语的文档数量,然后取该商的对数来获得
在这种情况下,排序的“词频”部分很可能导致“foo foo foo foo foo”在搜索“foo”时得分高于其他文档
此外,关于更改id时看到的效果:我不确定,但是我猜想ES必须在内部存储id
排序的文档(我不确定)。
如果是这种情况,则具有相同排序得分的2个文档将根据id作为决胜局进行排序。您当然可以定义多种排序以更改此行为(例如:sort = sorta + desc,sortb + desc。在这种情况下,sortb用作所有在scoreA得分相同的文档的决胜局)
关于elasticsearch - 为什么两个相同的文档分数不同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11229568/