elasticsearch 如何匹配嵌套属性而不使用ES中的嵌套属性

kx7yvsdv  于 5个月前  发布在  ElasticSearch
关注(0)|答案(2)|浏览(61)

我正在使用ElasticSearch为产品构建搜索功能。我们需要根据用户在搜索框中输入的内容,按类别,标题和品牌显示相关结果。例如,如果您输入Apple Laptop,则只希望显示Apple Laptops。我们不希望显示Apple Watches,Apple iPhone,Lenovo Laptops等。
问题是,如果我们有category_title,这个函数就可以完美地工作。但是,category实际上是一个嵌套的对象,有title和name属性。
初始查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "query_string": {
                        "query":  "apple~ AND laptop~",
                        "fields": [
                            "category_title",
                            "title",
                            "brand"
                        ]
                    }
                }
            ]
        }
    }
}

字符串
因此,查询应该如下所示:

{
    "query": {
        "bool": {
            "must": [
                {
                    "query_string": {
                        "query":  "apple~ AND laptop~",
                        "fields": [
                            "category.title",
                            "title",
                            "brand"
                        ]
                    }
                }
            ]
        }
    }
}


我怎样才能保持相同的搜索行为,仍然能够搜索类别。标题?
架构:

{
  "mappings": {
    "properties": {
      "brand": {
        "type": "keyword"
      },
      "category": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "keyword"
          },
          "title": {
            "type": "text"
          }
        }
      },
      "name": {
        "type": "keyword"
      },
      "title": {
        "type": "text"
      }
    }
  }
}

vhipe2zx

vhipe2zx1#

编辑:

我正在更新我的答案并分享一个解决方案。它不是最好的,但可以帮助你。
Elasticsearch copy_to

PUT product_stack2
{
  "mappings": {
    "properties": {
      "brand": {
        "type": "keyword",
        "copy_to": "search_field"
      },
      "category": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "keyword",
            "copy_to": "search_field"
          },
          "title": {
            "type": "text",
            "copy_to": "search_field"
          }
        }
      },
      "name": {
        "type": "keyword",
            "copy_to": "search_field"
      },
      "title": {
        "type": "text",
        "copy_to": "search_field"
      }
    }
  }
}
PUT product_stack2/_doc/1
{
  "name": "1",
  "brand": "apple",
  "category": {
    "name": "1",
    "title": "laptops"
  },
  "title": "Macbook Pro"
}
GET product_stack2/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "query_string": {
            "query": "apple~ AND laptop~",
            "fields": [
              "search_field"
            ]
          }
        }
      ]
    }
  }
}

结果:

i7uq4tfw

i7uq4tfw2#

我想你可能对嵌套字段的工作原理感到困惑。从你的评论来看,这是一个示例产品:

{
    "name": "1",
    "brand": "apple",
    "category": {
        "name": "1",
        "title": "laptops"
    },
    "title": "Macbook Pro"
}

字符串
但在这种情况下,category * 不是 * 一个嵌套字段。它在内部转换为"category.name": "1""category.title": "laptops"。如果category确实是一个嵌套字段,它通常看起来像这样:

{
    "name": "1",
    "brand": "apple",
    "category": [
        {
            "name": "real",
            "title": "laptops"
        },
        {
            "name": "fake",
            "title": "computers"
        },
        {
            "name": "real",
            "title": "macbooks"
        }
    ],
    "title": "Macbook Pro"
}


嵌套允许您单独查询每个子文档(例如,仅当category.name = real * 和 * category.title = laptops在该数组的同一元素中时才匹配结果)。
但对我来说,听起来你并不关心applelaptop是否需要在嵌套类别的同一个元素中。你只关心这两个词是否在那里。如果是这样的话,然后你应该要么**(1)不标记该字段为“嵌套”或(2)**或者你可以在Map中添加一个额外的标志include_in_parent。之后你可以在你的帖子中的原始简化查询中使用category.title
如果出于某种令人兴奋的原因,你需要调整你的查询以适应ElasticsearchMap(而不是调整Map以适应查询),那么我能想到的唯一方法就是做你想做的事情,它的功能类似于拥有一个category.title字段,这只会随着更多的关键字而变得更糟:

{
  "query": {
    "bool": {
      "must": [
       {
          "bool": {
            "should": [
              {
                "query_string": {
                  "query": "apple~",
                  "fields": [
                    "title",
                    "brand"
                  ]
                }
              },
              {
                "nested": {
                  "path": "category",
                  "query": {
                    "query_string": {
                      "query": "apple~",
                      "default_field": "category.title"
                    }
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "should": [
              {
                "query_string": {
                  "query": "laptop~",
                  "fields": [
                    "title",
                    "brand"
                  ]
                }
              },
              {
                "nested": {
                  "path": "category",
                  "query": {
                    "query_string": {
                      "query": "laptop~",
                      "default_field": "category.title"
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

相关问题