避免 ElasticSearch 查询中的幻数提升?
Avoiding magic-number boosts in ElasticSearch queries?
我希望由 ElasticSearch 查询生成的文档具有一个字段(称为 'fubar')设置为在查询时确定的特定值,以始终出现在没有 fubar 的文档之前设置为这些值之一。
例如,在查询时,我决定将 fubar 设置为 1、5 或 10 的文档排在所有其他文档之前。
现在我正在这样做,方法是使用 function_score 过滤作为 "in" 值列表的 fubar,并将过滤器的提升设置为 10 倍。然后将查询分数和这个增强过滤器相加。
这感觉像是一个 hack -- 我怎么确定不需要 100 倍的提升?是否有一种 "clean" 方法可以做到这一点而不对最大可能的文档分数做出假设?换句话说,有没有办法避免 'magic' 提升数字?
已编辑:修改了查询排序以匹配 OP 的澄清问题。
{
"query" : {"match_all" : {}},
"sort" : [
{"_script" : {
"script" : "[1, 10, 15].contains(doc['fubar'].value.toInteger()) ? 1 : 0",
"type" : "number",
"order" : "desc"
}},
"_score"
]
}
这种排序依赖于指定的脚本来动态确定每个文档中的 fubar
是否等于 1、10 或 15 排序。在此示例中,我选择将结果映射到 1 或 0,但我确信您可以使用任何其他方法来实现它。使用以下示例数据:
{"name":"Alice", "fubar":1}
{"name":"Bob", "fubar":21}
{"name":"Carol", "fubar":33}
{"name":"David", "fubar":17}
{"name":"Evelyn", "fubar":5}
{"name":"Fred", "fubar":10}
我得到了以下结果(为了便于阅读而截断了多余的位):
"hits" : [ {
"_index" : "test",
"_type" : "test",
"_id" : "1",
"_score" : 1.0,
"_source":{"fubar": 1, "name": "Alice"},
"sort" : [ 1.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "6",
"_score" : 1.0,
"_source":{"fubar": 10, "name": "Fred"},
"sort" : [ 1.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "4",
"_score" : 1.0,
"_source":{"fubar": 17, "name": "David"},
"sort" : [ 0.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "5",
"_score" : 1.0,
"_source":{"fubar": 5, "name": "Evelyn"},
"sort" : [ 0.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "2",
"_score" : 1.0,
"_source":{"fubar": 21, "name": "Bob"},
"sort" : [ 0.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "3",
"_score" : 1.0,
"_source":{"fubar": 33, "name": "Carol"},
"sort" : [ 0.0, 1.0 ]
} ]
请注意,Alice 和 Fred 首先返回,这是我们希望的行为。对于我的小案例,所有文档的得分都是 1.0,因此使用 _score
作为次要排序标准没有任何效果,但真实世界的数据(具有真实世界的得分)会考虑到这一点。
我希望由 ElasticSearch 查询生成的文档具有一个字段(称为 'fubar')设置为在查询时确定的特定值,以始终出现在没有 fubar 的文档之前设置为这些值之一。
例如,在查询时,我决定将 fubar 设置为 1、5 或 10 的文档排在所有其他文档之前。
现在我正在这样做,方法是使用 function_score 过滤作为 "in" 值列表的 fubar,并将过滤器的提升设置为 10 倍。然后将查询分数和这个增强过滤器相加。
这感觉像是一个 hack -- 我怎么确定不需要 100 倍的提升?是否有一种 "clean" 方法可以做到这一点而不对最大可能的文档分数做出假设?换句话说,有没有办法避免 'magic' 提升数字?
已编辑:修改了查询排序以匹配 OP 的澄清问题。
{
"query" : {"match_all" : {}},
"sort" : [
{"_script" : {
"script" : "[1, 10, 15].contains(doc['fubar'].value.toInteger()) ? 1 : 0",
"type" : "number",
"order" : "desc"
}},
"_score"
]
}
这种排序依赖于指定的脚本来动态确定每个文档中的 fubar
是否等于 1、10 或 15 排序。在此示例中,我选择将结果映射到 1 或 0,但我确信您可以使用任何其他方法来实现它。使用以下示例数据:
{"name":"Alice", "fubar":1}
{"name":"Bob", "fubar":21}
{"name":"Carol", "fubar":33}
{"name":"David", "fubar":17}
{"name":"Evelyn", "fubar":5}
{"name":"Fred", "fubar":10}
我得到了以下结果(为了便于阅读而截断了多余的位):
"hits" : [ {
"_index" : "test",
"_type" : "test",
"_id" : "1",
"_score" : 1.0,
"_source":{"fubar": 1, "name": "Alice"},
"sort" : [ 1.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "6",
"_score" : 1.0,
"_source":{"fubar": 10, "name": "Fred"},
"sort" : [ 1.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "4",
"_score" : 1.0,
"_source":{"fubar": 17, "name": "David"},
"sort" : [ 0.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "5",
"_score" : 1.0,
"_source":{"fubar": 5, "name": "Evelyn"},
"sort" : [ 0.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "2",
"_score" : 1.0,
"_source":{"fubar": 21, "name": "Bob"},
"sort" : [ 0.0, 1.0 ]
}, {
"_index" : "test",
"_type" : "test",
"_id" : "3",
"_score" : 1.0,
"_source":{"fubar": 33, "name": "Carol"},
"sort" : [ 0.0, 1.0 ]
} ]
请注意,Alice 和 Fred 首先返回,这是我们希望的行为。对于我的小案例,所有文档的得分都是 1.0,因此使用 _score
作为次要排序标准没有任何效果,但真实世界的数据(具有真实世界的得分)会考虑到这一点。