【问题标题】:Must match document with keyword if it occurs, must match other document if keyword doesn't occur如果出现则必须与关键字匹配文档,如果关键字不出现则必须匹配其他文档
【发布时间】:2021-07-15 07:19:46
【问题描述】:

我正在寻找一个查询以返回一个文档,该文档“如果关键字出现在搜索短语中,则必须将文档与关键字匹配,否则如果该关键字未出现在搜索中,则查找另一个不包含关键字的文档短语”。

您可以想象一个带有商店产品的索引,它可以是“常规”或“有一些不寻常的东西”,而当它是常规时,您不会将其添加到搜索词组中。

如果我们有这个产品:

  • “耐克 T 恤”(属性:[])
  • “阿迪达斯 T 恤”(属性:[“collectible”])

如果用户搜索“T 恤”,我们不希望他找到任何 收藏品。但是,当用户搜索“收藏 T 恤”时,我们希望他找到only 收藏品。这种关键字可以有多个。


例子:

我有一些文件:

[
  {
    "id": 1,
    "name": "First document",
    "variants": ["red", "big"]
  },
  {
    "id": 2,
    "name": "Second document",
    "variants": ["red"]
  },
  {
    "id": 3,
    "name": "Third entry",
    "variants": ["green", "big"]
  }
]

我有两个搜索词组可以转换为词条查询: H4>
  1. 出现关键字 (big):
{
  "query": {
    "bool" : {
      "must": {
        "match": {
          "name": {
            "query": "document"
          }
        }
      },
      "??? must or must_not ???" : {
        "terms": {
          "variants": ["some", "big", "search", "phrase"]
        }
      },
    }
  }
}
  1. 没有关键字出现:
{
  "query": {
    "bool" : {
      "must": {
        "match": {
          "name": {
            "query": "document"
          }
        }
      },
      "??? must or must_not ???" : {
        "terms": {
          "variants": ["some", "search", "phrase"]
        }
      },
    }
  }
}

现在第一次搜索我希望 Elasticsearch 返回 only 文档id: 1 and 3,第二次搜索我想返回 only 文档id: 2.

使用bool.must.terms.variants: ["some", "big", "search", "phrase"] 将返回我正在查找的一份文档,但使用 bool.must.terms.variants: ["some", "search", "phrase"] 将不会返回任何文档。

另一方面,如果我将must 替换为should,我会得到两个文档按分数正确排序,但我必须只匹配一个符合上述规则的文档。。 p>

【问题讨论】:

  • keyword (big)为什么文档3不匹配?
  • @nay 你是对的,文件 1 和 3 应该被退回。已更正。谢谢!
  • 第三个文档的名称应该是“第三个文档”而不是“第三个条目”吗?

标签: elasticsearch


【解决方案1】:

抱歉,这可能无法回答您的问题。由于我还不能创建 cmets,所以我发布了这个。

我不认为你可以用“一个”查询来做那个逻辑。您描述的逻辑是两步逻辑。

  1. 查找与variants 匹配的记录
  2. 如果没有返回记录,查找与variants 不匹配的记录

您需要第一步的结果来评估第二步。 据我了解,弹性搜索查询是单步的。查询被分发到保存数据的所有分片,每个分片将独立搜索并返回结果。即它不会与其他分片协调以检查其他分片是否匹配。

也许你可以试试 Aggregate。

【讨论】:

    【解决方案2】:

    正如@dna01 提到的,您需要发送两个后续请求:第一个请求查找与关键字匹配的文档,然后如果没有找到第二个请求,则查找与关键字不匹配的文档。

    您可以使用Multi Search API 省略第二个请求增加的额外延迟

    只需在一个请求中发送两个搜索。

    请求正文示例(让请求为“一些大搜索词组”和关键字“大”)。

    { }
    { "query": { "bool": {"must": [{"match": {"name": "document" }}, {"terms": {"variants": ["some", "big", "search", "phrase"]}}] } } }
    { }
    { "query": { "bool": {"must": [{"match": {"name": "document" }}, {"terms": {"variants": ["some", "big", "search", "phrase"]}}], "must_not": [{"terms": {"variants": ["big"]}}] } } }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      相关资源
      最近更新 更多