Elasticsearch DSL 查询 - 可选的术语和分数

Elasticsearch DSL queries - optional should terms & scores

我是 Elasticsearch 世界的新手,我可能遗漏了一些概念。

这是我不理解的场景:

我想根据以下条件查找文档:

映射:

PUT data
{
  "mappings": {
    "properties": {
      "createdAt": {
        "type":   "date",
        "format": "yyyy-MM-dd HH:mm:ss.SSSZ"
      },
      "category": {
        "type": "nested",
        "properties": {
          "name": {
            "type":   "text",
            "analyzer": "keyword"
          }
        }
      },
      "approved": {
        "type":   "text",
        "analyzer": "keyword"
      }
    }
  }
}

数据:

POST data/_create/1
{  
  "category": [
      {
        "name": "John G.",
        "level": "A"
      },
      {
        "name": "Mary F.",
        "level": "A"
      }
  ],
  "createdBy": "John",
  "createdAt": "2022-04-18 19:09:27.527+0200",
  "approved": "yes"
}

POST data/_create/2
{  
  "category": [
      {
        "name": "John G.",
        "level": "A"
      },
      {
        "name": "Chris T.",
        "level": "A"
      }
  ],
  "createdBy": "John",
  "createdAt": "2022-04-18 19:09:27.527+0200",
  "approved": "no"
}

POST data/_create/3
{  
  "category": [
      {
        "name": "John G.",
        "level": "C"
      },
      {
        "name": "Phil C.",
        "level": "C"
      }
  ],
  "createdBy": "John",
  "createdAt": "2022-04-18 19:09:27.527+0200",
  "approved": "no"
}

POST data/_create/4
{  
  "category": [
      {
        "name": "John G.",
        "level": "A"
      },
      {
        "name": "Chris T.",
        "level": "A"
      }
  ],
  "createdBy": "John",
  "createdAt": "2020-04-18 19:09:27.527+0200",
  "approved": "yes"
}

POST data/_create/5
{  
  "category": [
      {
        "name": "Unknown A.",
        "level": "A"
      },
      {
        "name": "Unknown B.",
        "level": "A"
      }
  ],
  "createdBy": "Unknown",
  "createdAt": "2020-08-18 19:09:27.527+0200",
  "approved": "yes"
}

查询:

GET data/_search
{
  "query": {
    "nested": {
      "path": "category",
      "query": {
        "bool": {
          "must": [
            {"match": {"category.level": "A"}}
          ],
          "should": [
            {"term": {"category.name": "John G."}},
            {"term": {"category.name": "Chris T."}},
            {"term": {"approved": "yes"}}
          ],
          "minimum_should_match": 1
        }
      }
    }
  }
}

回复:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.4455402,
    "hits" : [
      {
        "_index" : "data",
        "_id" : "2",
        "_score" : 1.4455402,
        "_source" : {
          "category" : [
            {
              "name" : "John G.",
              "level" : "A"
            },
            {
              "name" : "Chris T.",
              "level" : "A"
            }
          ],
          "createdBy" : "John",
          "createdAt" : "2022-04-18 19:09:27.527+0200",
          "approved" : "no"
        }
      },
      {
        "_index" : "data",
        "_id" : "4",
        "_score" : 1.4455402,
        "_source" : {
          "category" : [
            {
              "name" : "John G.",
              "level" : "A"
            },
            {
              "name" : "Chris T.",
              "level" : "A"
            }
          ],
          "createdBy" : "John",
          "createdAt" : "2020-04-18 19:09:27.527+0200",
          "approved" : "yes"
        }
      },
      {
        "_index" : "data",
        "_id" : "1",
        "_score" : 1.151647,
        "_source" : {
          "category" : [
            {
              "name" : "John G.",
              "level" : "A"
            },
            {
              "name" : "Mary F.",
              "level" : "A"
            }
          ],
          "createdBy" : "John",
          "createdAt" : "2022-04-18 19:09:27.527+0200",
          "approved" : "yes"
        }
      }
    ]
  }
}

问题:

  1. 为什么返回的第一个文档是 approval = no?我期待带有 approval = yes 的文档会得到更好的评分。
  2. 为什么索引 = 5 的文档(它不符合条件 category.name,但符合 approved = yes)没有被返回?
  3. approved = yes 的可选性未在上述查询中表达。我怎样才能用 minimum_should_match: 0 创建一种额外的分隔 should 术语?可以增加分数但不会过滤结果的东西。

我用你的映射和示例数据尝试了你的场景,发现了问题,你在导致问题的 nested 查询上下文中使用了 approved:yes,这就是导致问题的原因,如果您将查询更改为下面的 (基本上在 should 块中使用 approved:yes 但在 nested 查询之外),它会解决您所有的问题。

{
    "query": {
        "bool": {
            "should": [
                {
                    "nested": {
                        "path": "category",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "match": {
                                            "category.level": "A"
                                        }
                                    }
                                ],
                                "should": [
                                    {
                                        "term": {
                                            "category.name": "John G."
                                        }
                                    },
                                    {
                                        "term": {
                                            "category.name": "Chris T."
                                        }
                                    }
                                ]
                            }
                        }
                    }
                },
                {
                    "term": {
                        "approved": "yes"
                    }
                }
            ]
        }
    }
}

和搜索结果

"hits": [
            {
                "_index": "71967271",
                "_id": "4",
                "_score": 1.9845366,
                "_source": {
                    "category": [
                        {
                            "name": "John G.",
                            "level": "A"
                        },
                        {
                            "name": "Chris T.",
                            "level": "A"
                        }
                    ],
                    "createdBy": "John",
                    "createdAt": "2020-04-18 19:09:27.527+0200",
                    "approved": "yes"
                }
            },
            {
                "_index": "71967271",
                "_id": "2",
                "_score": 1.4455402,
                "_source": {
                    "category": [
                        {
                            "name": "John G.",
                            "level": "A"
                        },
                        {
                            "name": "Chris T.",
                            "level": "A"
                        }
                    ],
                    "createdBy": "John",
                    "createdAt": "2022-04-18 19:09:27.527+0200",
                    "approved": "no"
                }
            },
            {
                "_index": "71967271",
                "_id": "1",
                "_score": 1.2437345,
                "_source": {
                    "category": [
                        {
                            "name": "John G.",
                            "level": "A"
                        },
                        {
                            "name": "Mary F.",
                            "level": "A"
                        }
                    ],
                    "createdBy": "John",
                    "createdAt": "2022-04-18 19:09:27.527+0200",
                    "approved": "yes"
                }
            },
            {
                "_index": "71967271",
                "_id": "5",
                "_score": 0.7968255,
                "_source": {
                    "category": [
                        {
                            "name": "Unknown A.",
                            "level": "A"
                        },
                        {
                            "name": "Unknown B.",
                            "level": "A"
                        }
                    ],
                    "createdBy": "Unknown",
                    "createdAt": "2020-08-18 19:09:27.527+0200",
                    "approved": "yes"
                }
            }
        ]

您需要使用下面的查询,其中有主要的 bool 查询。它有第一个带有嵌套查询的 must 子句,它有 bool 查询 category.level 字段,然后另一个 bool 查询带有 should 子句 category.name字段。

现在主 bool 查询有 approved 的 should 子句,用于提升具有 yes 值的结果(这在 nested 查询之外)。

POST data/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "category",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "category.level": {
                        "value": "a"
                      }
                    }
                  },
                  {
                    "bool": {
                      "should": [
                        {
                          "term": {
                            "category.name": "John G."
                          }
                        },
                        {
                          "term": {
                            "category.name": "Chris T."
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "approved": "yes"
          }
        }
      ]
    }
  }
}

结果:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.9845366,
    "hits" : [
      {
        "_index" : "data",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.9845366,
        "_source" : {
          "category" : [
            {
              "name" : "John G.",
              "level" : "A"
            },
            {
              "name" : "Chris T.",
              "level" : "A"
            }
          ],
          "createdBy" : "John",
          "createdAt" : "2020-04-18 19:09:27.527+0200",
          "approved" : "yes"
        }
      },
      {
        "_index" : "data",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.6906434,
        "_source" : {
          "category" : [
            {
              "name" : "John G.",
              "level" : "A"
            },
            {
              "name" : "Mary F.",
              "level" : "A"
            }
          ],
          "createdBy" : "John",
          "createdAt" : "2022-04-18 19:09:27.527+0200",
          "approved" : "yes"
        }
      },
      {
        "_index" : "data",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.4455402,
        "_source" : {
          "category" : [
            {
              "name" : "John G.",
              "level" : "A"
            },
            {
              "name" : "Chris T.",
              "level" : "A"
            }
          ],
          "createdBy" : "John",
          "createdAt" : "2022-04-18 19:09:27.527+0200",
          "approved" : "no"
        }
      }
    ]
  }
}

Why the first document returned is an approval = no? I was expecting that docs with approval = yes would be better scored.

因为您在 nested 查询中有 should 子句,并且它与任何文档都不匹配,因为 approvedcategory 之外,因此它不会改变分数。

Why doc with index = 5 (it doesn't attend the criteria category.name, but it does for approved = yes) is not being returned?

它已被您的 must 子句删除,但是如果您还需要 index =5 文档,那么您可以添加两个 should 子句,一个用于嵌套,一个用于 approved,它将解决你的问题。

我的回答也解决了你的问题3。