【问题标题】:Elasticsearch search with nested properties具有嵌套属性的 Elasticsearch 搜索
【发布时间】:2021-05-06 14:59:01
【问题描述】:

我有一个实例,其中存储了具有各种属性的文章。但可能有些项目根本没有属性。有无数的属性和赋值,都是随机顺序的。

现在的问题是,不幸的是它并没有按照我想要的方式工作。属性受到尊重,但属性的顺序似乎很重要。但也可能是实例中的条目中有很多属性,在搜索查询中只查询到了 1-2 个,并且这些值可能会有细微的偏差。

目标是找到尽可能相似的条目,无论属性的顺序如何。

谁能帮我解决这个问题?

弹性实例信息:

 "_index" : "articles",
    "_type" : "_doc",
    "_id" : "fYjaQXkBBdCju4scstN_",
    "_score" : 1.0,
    "_source" : {
      "position" : "400.000",
      "beschreibung" : "asc",
      "menge" : 24.0,
      "einheit" : "St",
      "properties" : [
        {
          "desc" : "Farbe",
          "val" : "rot"
        },
        {
          "desc" : "Material",
          "val" : "Holz"
        },
        {
          "desc" : "Länge",
          "val" : "20 cm"
        },
        {
          "desc" : "Breite",
          "val" : "100 km"
        }
      ]
    }
  }

我当前查询的嵌套部分:

[nested] => Array
(
    [path] => properties
    [query] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [bool] => Array
                                (
                                    [should] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [match] => Array
                                                        (
                                                            [properties.desc] => Farbe
                                                        )

                                                )

                                            [1] => Array
                                                (
                                                    [match] => Array
                                                        (
                                                            [properties.val] => rot
                                                        )

                                                )

                                        )

                                )

                        )

                )

            [1] => Array
                (
                    [0] => Array
                        (
                            [bool] => Array
                                (
                                    [should] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [match] => Array
                                                        (
                                                            [properties.desc] => Länge
                                                        )

                                                )

                                            [1] => Array
                                                (
                                                    [match] => Array
                                                        (
                                                            [properties.val] => 22 cm
                                                        )

                                                )

                                        )

                                )

                        )

                )

            [2] => Array
                (
                    [0] => Array
                        (
                            [bool] => Array
                                (
                                    [should] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [match] => Array
                                                        (
                                                            [properties.desc] => Material
                                                        )

                                                )

                                            [1] => Array
                                                (
                                                    [match] => Array
                                                        (
                                                            [properties.val] => Holz
                                                        )

                                                )

                                        )

                                )

                        )

                )

        )

)

【问题讨论】:

  • 您对“属性”使用哪种字段类型?
  • “属性”字段的类型为“嵌套”
  • 我不明白的是,为什么如果我更改查询以不搜索“Länge”“22 cm”但搜索“Länge”“20 cm”,即精确搜索条目中也包含的值。因此,如果我精确搜索一个属性及其值(也包含在条目中),或者我稍微更改搜索属性的值,那么分数值没有区别。分数结果保持不变。
  • 在我看来,您发布的查询很难阅读,也许您可​​以编辑问题并以 JSON 格式发布。这让其他人更容易重现你的错误:)

标签: elasticsearch nested


【解决方案1】:

您的查询中有两个问题导致奇怪的结果:

  1. 您正在对具有多个术语的文本字段使用 match 查询。所以当做一个

    "match": {
      "properties.val": "22 cm",
    }
    

    ,Elasticsearch 在 properties.val 字段中搜索“22”或“cm”。我假设你想匹配整个短语,所以你可以在这里使用 match_phrase。或者,您可以将该单元放入自己的字段中。另一种选择是使用 operator 参数:

    "match": {
      "properties.val": {
        "query": "20 cm",
        "operator": "and"
      }
    }
    

    但请注意,这不是在寻找确切的短语。例如“20 30 cm”也会匹配,但也许这可能适合您的情况。

  2. 您在属性级别使用 should 子句。因此,您基本上是在要求具有属性的文档,“在描述中应该有 Farbe,在值中应该有 rot”,但这将匹配以下所有示例:

    "properties" : [
       {
         "desc" : "Farbe",
         "val" : "blau"
       }
      ]
    

   "properties" : [
      {
        "desc" : "Material",
        "val" : "rot"
      }
     ]

   "properties" : [
      {
        "desc" : "Farbe",
        "val" : "blau"
      },
      {
        "desc" : "Material",
        "val" : "rot"
      }
     ]

所以你需要一个 bool 查询(具有 mustfilter 子句)来匹配你想要匹配的每个属性和一个 bool 查询每个属性都有一个 should 子句。您对问题的查询可能是这样的:

{
  "query": {
    "bool": {
      "should": [
        {
          "nested": {
            "path": "properties",
            "query": {
              "bool": {
                "filter": [
                  {
                    "match": {
                      "properties.desc": "Farbe"
                    }
                  }
                ],
                "must": [
                  {
                    "match_phrase": {
                      "properties.val": "rot"
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "properties",
            "query": {
              "bool": {
                "filter": [
                  {
                    "match": {
                      "properties.desc": "Länge"
                    }
                  }
                ],
                "must": [
                  {
                    "match_phrase": {
                      "properties.val": "22 cm"
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "properties",
            "query": {
              "bool": {
                "filter": [
                  {
                    "match": {
                      "properties.desc": "Material"
                    }
                  }
                ],
                "must": [
                  {
                    "match_phrase": {
                      "properties.val": "Holz"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

请试一试,如果这能达到预期的效果。 您仍然可以调整查询,例如使用 minimum_should_match 或定义每个匹配属性给出的分数。

【讨论】:

  • 嗨@Chules,感谢您提供这个有用的答案!我会检查你的积分,我相信它会对我有很大帮助。
  • 嘿@Maisen1886,我很高兴能帮上忙。如果这解决了您的问题,请考虑将其标记为已接受的答案:)
  • 哦,当然! 8-)
猜你喜欢
  • 2019-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多