【问题标题】:Storing nested objects in elastic search在弹性搜索中存储嵌套对象
【发布时间】:2018-09-27 06:34:04
【问题描述】:

我有一个类似于下面的 3 级嵌套对象,我想在弹性搜索中索引这些对象。这里的要求是用户将编写一个搜索查询关键字,如“keyword1 keyword2 ...”,我想返回包含所有这些关键字的对象(在任何级别,即 AND 操作)。

   [  
   {  
      "country":[  
         {  
            "name":"India",
            "ext_code":"91",
            "states":[  
               {  
                  "name":"Karnataka",
                  "ext_code":"04",
                  "cities":[  
                     {  
                        "name":"Bangalore",
                        "ext_code":"080"
                     }
                  ]
               }
            ]
         }
      ]
   }
]

目前,我使用以下映射以嵌套格式存储它们:

{
    "mappings":{
        "doc":{
            "properties":{
                "name": {"type":"text"},
                "ext_code": {"type":"text"}
                "state" {
                    "type": "nested",
                    "properties": {
                        "name": {"type":"text"},
                        "ext_code": {"type":"text"}
                        "city" {
                            "type": "nested",
                            "properties": {
                                "name": {"type":"text"}
                                "ext_code": {"type":"text"}
                            }
                        }
                    }
                }
            }
        }
    }
}

在搜索时,我通过弹性搜索一个嵌套查询来搜索所有级别,如下所示:

{
    "query": {
        "bool": {
            "should": [
                {
                    "multi_match": {
                        "query": "keyword1 keyword2 ...",
                        "fields": ['name'] 
                    }
                },
                {
                    "nested": {
                        "path": 'state',
                        "query": {
                            "multi_match": {
                                "query": "keyword1 keyword2 ...",
                                "fields": ['state.name']
                            }
                        }
                    }
                },
                {
                    "nested": {
                        "path": 'state.city',
                        "query": {
                            "multi_match": {
                                "query": "keyword1 keyword2 ...",
                                "fields": ['state.city.name']
                            }
                        }
                    }
                }
            ]
        }
    }
}

当发送多个标记进行搜索时,它会应用 OR 操作返回包含任何搜索标记的文档。

有没有办法配置 Elastic Search 以对搜索查询中的多个标记执行 AND 操作?

【问题讨论】:

  • 嗨 Lokesh,技术上可行的总会得到解决方案,但有时您认为如果您不知道要完成的目标的目的,某些解决方案会更难,您为什么选择嵌套类型?
  • 你的意思是我可以将它存储为平面结构?
  • 是的,但是当然,这一切都取决于您要运行的查询类型,一位 ES 工程师曾经告诉我,嵌套类型的结果最终通过将结构转换为优化(cpu 和内存,因此成本)扁平化并在客户端添加一些工作。
  • 展平数据对分析(使用 Kibana)有影响吗?
  • 巨大,kibana 是为“时间序列优先”的数据模式而设计的,平面是时间序列中的王者,所以是的。

标签: elasticsearch


【解决方案1】:

一种解决方案是在自定义all field 中索引name 字段的所有值。首先像这样定义你的索引和映射:

PUT index
{
  "mappings": {
    "doc": {
      "properties": {
        "all": {                 <-- all field that will contain all values
          "type": "text"
        },
        "name": {
          "type": "text",
          "copy_to": "all"       <-- copy value to all field
        },
        "ext_code": {
          "type": "text"
        },
        "state": {
          "type": "nested",
          "properties": {
            "name": {
              "type": "text",
              "copy_to": "all"       <-- copy value to all field
            },
            "ext_code": {
              "type": "text"
            },
            "city": {
              "type": "nested",
              "properties": {
                "name": {
                  "type": "text",
                  "copy_to": "all"       <-- copy value to all field
                },
                "ext_code": {
                  "type": "text"
                }
              }
            }
          }
        }
      }
    }
  }
}

然后索引您的文档:

POST index/doc
{
  "name": "India",
  "ext_code": "91",
  "state": [
    {
      "name": "Karnataka",
      "ext_code": "04",
      "city": [
        {
          "name": "Bangalore",
          "ext_code": "080"
        }
      ]
    }
  ]
}

最后,使用简单的匹配查询,您可以在文档的任何位置搜索任何值:

POST index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "all": {
              "query": "bangalore india",
              "operator": "and"
            }
          }
        }
      ]
    }
  }
}

【讨论】:

    【解决方案2】:

    请尝试关注

    {
        "query": {
            "bool": {
                "should": [
                    {
                        "simple_query_string": {
                            "query": "keyword1 keyword2 ...",
                            "fields": ['name'] ,
                            "default_operator": "and"
                        }
                    },
                    {
                        "nested": {
                            "path": 'state',
                            "query": {
                                "simple_query_string": {
                                    "query": "keyword1 keyword2 ...",
                                    "fields": ['state.name'],
                                    "default_operator": "and"
                                }
                            }
                        }
                    },
                    {
                        "nested": {
                            "path": 'state.city',
                            "query": {
                                "simple_query_string": {
                                    "query": "keyword1 keyword2 ...",
                                    "fields": ['state.city.name'],
                                    "default_operator": "and"
                                }
                            }
                        }
                    }
                ]
            }
        }
    }
    

    我认为 multi_match 不适合这个要求。简单查询字符串或查询字符串查询更适合此目的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      相关资源
      最近更新 更多