0

我在 elasticsearch 的文档中有一个名为 tags 的字段,结构如下。

tags = [
    {
        "id": 10,
        "related": [9, 8, 7]
    }
]

我现在运行一个带有列表的过滤器。例如[10, 9]。我只想过滤那些包含 id 或相关列表中所有项目的文档。如果我用 搜索[9, 8],应该返回上面的文档。如果我使用 搜索[9, 12],则不应返回上述文档,因为 12 既不存在于 id 也不存在于相关中。

我尝试使用术语过滤器,但它只是做或。是否有任何技术可以实现上述目标。

此外,我想为包含 id 中给定项目的文档提供比包含related.

4

1 回答 1

2

问题分析

让我们在以下子问题中解决您的问题:

  • (P1)检查数组中提供的所有项是否都出现在tags.idtags.related中。这可以进一步分解为:
    • (P1.1)检查数组中提供的所有术语是否都存在于字段中
    • (P1.2)检查数组中提供的所有术语是否分布在不同的字段中
  • (P2)为具有任何提供的术语的文档分配更高的分数tags.id

解决方案

要解决(P1.1),您可以使用terms_setElasticsearch v6.6 中提供的查询(请参阅文档)。

为了解决(P1.2),我会将tags.id和的所有值复制tags.related到一个新的自定义字段中,例如tags.all. 这可以使用以下copy_to属性来实现:

{
  "mappings": {
    "_doc": {
      "properties": {
        "tags": {
          "properties": {
            "id": { 
              "type": "long",
              "copy_to": "tags.all"
            },
            "related": { 
              "type": "long",
              "copy_to": "tags.all"
            }
          }
        }
      }
    }
  }
}

然后,要解决(P1),您可以terms_set针对tags.all. 例如,

{
  "query": {
    "terms_set": {
      "tags.all": {
        "terms": [ 9, 8 ],
        "minimum_should_match_script": {
          "source": "2"
        }
      }
    }
  }
}

最后,为了解决(P2),您可以创建一个布尔should查询,其中包括 (i) 上述terms_set查询,(ii)仅terms针对的查询tags.id,它具有更高的提升因子。IE,

{
  "query": {
    "bool": {
      "should": [
        {
          "terms_set": {
            "tags.all": {
              "terms": [ 9, 8 ],
              "minimum_should_match_script": {
                "source": "2"
              }
            }
          }
        },
        {
          "terms": {
            "tags.id": {
              "value": [ 9, 8 ],
              "boost": 2
            }
          }
        }
      ]
    }
  }
}
于 2019-03-06T15:30:56.980 回答