我有这个简单的文档集:
{
id : 1,
book_ids : [2,3],
collection_ids : ['a','b']
},
{
id : 2,
book_ids : [1,2]
}
如果我运行此过滤器查询,它将匹配两个文档:
{
bool: {
filter: [
{
bool: {
should: [
{
bool: {
must_not: {
exists: {
field: 'book_ids'
}
}
}
},
{
bool: {
filter: {
term: {
book_ids: 2
}
}
}
}
]
}
},
{
bool: {
should: [
{
bool: {
must_not: {
exists: {
field: 'collection_ids'
}
}
}
},
{
bool: {
filter: {
term: {
collection_ids: 'a'
}
}
}
}
]
}
}
]
}
}
问题是我想对这些文档进行排序,我希望首先返回第一个 (id: 1(,因为它与提供的book_ids
值和collection_ids
值匹配。
像这样的简单排序子句不起作用:
[
'book_ids',
'collection_ids'
]
因为它将返回第一个文档 2,因为数组的第一个值book_ids
。
编辑:这是我面临的问题的一个简化示例,在应该子句中有 N 个这样的子句。此外,子句之间有一个顺序,正如我试图用sort
片段反映的那样:与第一个子句(book_ids
(匹配的结果应该出现在与第二个子句(collection_ids
(匹配的结果之前。我真的在寻找某种SQL排序操作,我只会考虑字段数组的匹配值。一个可行的选项可能是根据预期的排序顺序为每个term
子句分配递减constant_scores,ES 必须将此子分数相加以计算最终分数。但是我不知道该怎么做,或者是否有可能。
奖金问题: ElasticSearch 有什么方法可以返回某种只包含匹配值的新文档?以下是我对上述过滤器查询的响应所期望的:
{
id : 1,
book_ids : [2],
collection_ids : ['a']
},
{
id : 2,
book_ids : [2]
}
我认为您对恒定分数的想法是正确的。我认为你可以这样做:
{
query: {
bool: {
must: [
{
bool: {
should: [
{
bool: {
must_not: {
exists: {
field: 'book_ids'
}
}
}
},
{
constant_score: {
filter: {
term: {
book_ids: 2
}
},
boost: 100
}
}
]
}
},
{
bool: {
should: [
{
bool: {
must_not: {
exists: {
field: 'collection_ids'
}
}
}
},
{
constant_score: {
filter: {
term: {
collection_ids: 'a'
}
},
boost: 50
}
}
]
}
}
]
}
}
}
我认为您使用常量分数唯一缺少的可能是顶级查询需要must
,而不是filter
。(筛选器没有评分,所有分数均为 0。
另一种方法是将筛选器放入function_score
查询中(但将其保留为筛选器(,然后根据需要计算分数(https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html(
至于奖金问题,如果您使用脚本字段来过滤和添加新字段,这是可能的(https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html(,但不可能以直接的方式进行。在收到结果后执行该筛选可能更容易且更有意义,除非您的值中有很长的列表。