【问题标题】:ElasticSearch adjacent words for nested queries over multiple nested fieldsElasticSearch 对多个嵌套字段的嵌套查询的相邻词
【发布时间】:2021-09-09 05:57:45
【问题描述】:

要搜索嵌套(或不嵌套)查询的相邻单词,解决方案如下(答案见here):

{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "metadata",
            "query": {
              "bool": {
                "must": [
                  {
                    "wildcard": {
                      "metadata.text": "*antonio*"
                    }
                  },
                  {
                    "wildcard": {
                      "metadata.text": "*banderas*"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

这工作正常。但是,应该有多个嵌套字段,在其中以相同的方式搜索 *antonio* *banderas*,假设现在我们有这个映射:

{
    "mappings:": {
        "properties": {
            "text": {
                "type": "text"
            },
            "metadata": {
                "type": "nested",
                "properties": {
                    "text": {
                        "type": "text"
                    }
                }
            },
            "other_metadata": {
                "type": "nested",
                "properties": {
                    "text": {
                        "type": "text"
                    }
                }
            }
        }
    }
}

如果我想在metadataother_metadata 两个嵌套字段中搜索相邻的单词,我应该使用match 还是should? 我想要一个匹配至少一个模式元数据或其他元数据的结果,所以我想使用should并将minimum_should_match设置为查询的令牌数(由a分隔\s - 空格字符)这样:

{
    "should": [{
            "nested": {
                "path": "metadata",
                "query": {
                    "bool": {
                        "must": {
                            "wildcard": {
                                "metadata.text": "*antonio*"
                            }
                        }
                    }
                },
                "ignore_unmapped": true
            }
        },
        {
            "nested": {
                "path": "metadata",
                "query": {
                    "bool": {
                        "must": {
                            "wildcard": {
                                "metadata.text": "*banderas*"
                            }
                        }
                    }
                },
                "ignore_unmapped": true
            }
        },
        {
            "nested": {
                "path": "other_metadata",
                "query": {
                    "bool": {
                        "must": {
                            "wildcard": {
                                "other_metadata.text": "*antonio*"
                            }
                        }
                    }
                },
                "ignore_unmapped": true
            }
        },
        {
            "nested": {
                "path": "other_metadata",
                "query": {
                    "bool": {
                        "must": {
                            "wildcard": {
                                "other_metadata.text": "*banderas*"
                            }
                        }
                    }
                },
                "ignore_unmapped": true
            }
        }
    ],
    "minimum_should_match": 2
}

这似乎可行,但我的疑问如下:这里的minimum_should_match=2 条件将确保这四个条件中至少有两个匹配,但不能保证这两个匹配条件都是与相同的模式相关(比如metadata 两个词*antonio**banderas*。如果是这样,如何确保?也许使用must?但是如何?

【问题讨论】:

    标签: elasticsearch elasticsearch-7


    【解决方案1】:

    你可以做这样的子查询:

    bool => should => bool => filter/must/should

    {
      "query": {
        "bool": {
          "minimum_should_match": 1,
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "nested": {
                      "ignore_unmapped": true,
                      "path": "metadata",
                      "query": {
                        "bool": {
                          "must": {
                            "wildcard": {
                              "metadata.text": "*antonio*"
                            }
                          }
                        }
                      }
                    }
                  },
                  {
                    "nested": {
                      "ignore_unmapped": true,
                      "path": "metadata",
                      "query": {
                        "bool": {
                          "must": {
                            "wildcard": {
                              "metadata.text": "*banderas*"
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "nested": {
                      "ignore_unmapped": true,
                      "path": "other_metadata",
                      "query": {
                        "bool": {
                          "must": {
                            "wildcard": {
                              "other_metadata.text": "*antonio*"
                            }
                          }
                        }
                      }
                    }
                  },
                  {
                    "nested": {
                      "ignore_unmapped": true,
                      "path": "other_metadata",
                      "query": {
                        "bool": {
                          "must": {
                            "wildcard": {
                              "other_metadata.text": "*banderas*"
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
    

    【讨论】:

    • 谢谢!这几乎可以完美地工作,但有一种“缺点”:如果您搜索 *marq* *marquez*,您将得到 gabriel garcias marquez,显然是因为 marquez 中存在 marq,而我预计没有结果或结果至少包含两个单词marq marquez。这是由于尾随 * 造成的吗?
    • * 仅当您想匹配多个 marq 时才需要此处,例如 randommarqmarqrandomrandmarqrand 等。如果您只想要 marq 则删除 @ 987654336@
    • 好吧,你说得对,我想我明白了!基本上对于某些字段,假设text 我有一个autocomplete 自定义分析器 - 请参阅此处gist.github.com/loretoparisi/dc1cdd4dea29a83e326a81a00fae2775 我假设在同一字段上拥有这个自动完成分析器+一个wildcard 可能会使精确搜索“无效” * + term + *term?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    • 2020-02-15
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多