【问题标题】:Elasticsearch multi level nested queryElasticsearch 多级嵌套查询
【发布时间】:2015-10-09 16:02:26
【问题描述】:

具有这样的多级嵌套字段的映射:

{
  otherFields....,
  nestedField: {
    type: "nested",
    include_in_parent: true,
    multiple: true,
    properties: {
      province: {
        type: "nested",
        include_in_parent: true,
        multiple: true
      },
      properties: {
        comuni: {
          type: "nested",
          include_in_parent: true,
          multiple: true,
          properties: {
            nome: {
              type: "string"
            },
            parziale: {
              type: "boolean"
            }
          }
        },
        nome: {
          type: "string"
        }
      }
    }
  },
  regione: {
    type: "string"
  }
}

文档中提到可以对该字段https://www.elastic.co/guide/en/elasticsearch/reference/1.7/query-dsl-nested-query.html 执行查询。

使用这个查询:

{
  "size": 1,
  "version": true,
  "query": {
    "filtered": {
      "query": {
        "function_score": {
          "query": {
            "bool": {
              "must": [
                {
                  "regex_term": {
                    "field_2": {
                      "term": ".*701.*",
                      "ignorecase": true
                    }
                  }
                }
              ]
            }
          },
          "functions": [
            {
              "script_score": {
                "script": "_score * -doc['field_2'].value.length()"
              }
            }
          ]
        }
      },
      "filter": {
        "nested": {
          "path": "nestedField",
          "filter": {
            "bool": {
              "must": [
                {
                  "term": {
                    "nestedField.regione": "Lazio"
                  }
                },
                {
                  "bool": {
                    "must": [
                      {
                        "or": {
                          "filters": [
                            {
                              "term": {
                                "nestedField.province.nome": "Pordenone"
                              }
                            },
                            {
                              "not": {
                                "filter": {
                                  "exists": {
                                    "field": "nestedField.province.nome"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      },
                      {
                        "or": {
                          "filters": [
                            {
                              "term": {
                                "nestedField.province.comuni.nome": "Udine"
                              }
                            },
                            {
                              "not": {
                                "filter": {
                                  "exists": {
                                    "field": "nestedField.province.comuni.nome"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

函数得分部分看起来不错,但在嵌套过滤器部分都有一些问题。 数据如下:

{
  "_source": {
    "otheFields" ...,
    "nestedField": [
      {
        "regione": "Lazio"
      },
      {
        "province": [
          {
            "nome": "Venezia"
          },
          {
            "nome": "Treviso"
          }
        ],
        "regione": "Veneto"
      },
      {
        "province": [
          {
            "comuni": [
              {
                "nome": "Varmo",
                "parziale": false
              }
            ],
            "nome": "Udine"
          }
        ],
        "regione": "Friuli venezia giulia"
      }
    ]
  }
}

即使省字段丢失,查询也找不到给定的记录,相反,如果我们对 regione 使用“Veneto”,对 provincia.nome 使用“Treviso”,并且在另一个嵌套中使用 comune 字段,它就可以正常工作对象。

为什么这个查询不起作用?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    尝试将您的术语更改为小写。由于您没有在映射中指定分析器,因此使用了 standard analyzer,它将术语转换为小写。

    您的查询非常复杂,起初我认为您可能需要更多 "nested" 子句,但是当我执行以下操作时,它似乎有效。 (我确实很快完成了这个,所以如果我在这里展示的内容由于某种原因对你不起作用,请告诉我。)

    我不得不删除"query" 部分,因为我在"regex_term" 上遇到了错误,但如果我没看错的话,如果我们只有一个文档,那应该不会影响结果。

    所以我创建了一个这样的索引(在"province" 的定义之后,你的一个大括号放错了位置):

    PUT /test_index
    {
       "settings": {
          "number_of_shards": 1
       },
       "mappings": {
          "doc": {
             "properties": {
                "nestedField": {
                   "type": "nested",
                   "include_in_parent": true,
                   "multiple": true,
                   "properties": {
                      "province": {
                         "type": "nested",
                         "include_in_parent": true,
                         "multiple": true,
                         "properties": {
                            "comuni": {
                               "type": "nested",
                               "include_in_parent": true,
                               "multiple": true,
                               "properties": {
                                  "nome": {
                                     "type": "string"
                                  },
                                  "parziale": {
                                     "type": "boolean"
                                  }
                               }
                            },
                            "nome": {
                               "type": "string"
                            }
                         }
                      }
                   },
                   "regione": {
                      "type": "string"
                   }
                }
             }
          }
       }
    }
    

    添加了您的文档:

    PUT /test_index/doc/1
    {
       "nestedField": [
          {
             "regione": "Lazio"
          },
          {
             "province": [
                {
                   "nome": "Venezia"
                },
                {
                   "nome": "Treviso"
                }
             ],
             "regione": "Veneto"
          },
          {
             "province": [
                {
                   "comuni": [
                      {
                         "nome": "Varmo",
                         "parziale": false
                      }
                   ],
                   "nome": "Udine"
                }
             ],
             "regione": "Friuli venezia giulia"
          }
       ]
    }
    

    然后运行这个修改后的查询:

    POST /test_index/_search
    {
       "size": 1,
       "version": true,
       "query": {
          "filtered": {
             "filter": {
                "nested": {
                   "path": "nestedField",
                   "filter": {
                      "bool": {
                         "must": [
                            {
                               "term": {
                                  "nestedField.regione": "lazio"
                               }
                            },
                            {
                               "bool": {
                                  "must": [
                                     {
                                        "or": {
                                           "filters": [
                                              {
                                                 "term": {
                                                    "nestedField.province.nome": "pordenone"
                                                 }
                                              },
                                              {
                                                 "not": {
                                                    "filter": {
                                                       "exists": {
                                                          "field": "nestedField.province.nome"
                                                       }
                                                    }
                                                 }
                                              }
                                           ]
                                        }
                                     },
                                     {
                                        "or": {
                                           "filters": [
                                              {
                                                 "term": {
                                                    "nestedField.province.comuni.nome": "udine"
                                                 }
                                              },
                                              {
                                                 "not": {
                                                    "filter": {
                                                       "exists": {
                                                          "field": "nestedField.province.comuni.nome"
                                                       }
                                                    }
                                                 }
                                              }
                                           ]
                                        }
                                     }
                                  ]
                               }
                            }
                         ]
                      }
                   }
                }
             }
          }
       }
    }
    

    文件被退回:

    {
       "took": 4,
       "timed_out": false,
       "_shards": {
          "total": 1,
          "successful": 1,
          "failed": 0
       },
       "hits": {
          "total": 1,
          "max_score": 1,
          "hits": [
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "1",
                "_version": 1,
                "_score": 1,
                "_source": {
                   "nestedField": [
                      {
                         "regione": "Lazio"
                      },
                      {
                         "province": [
                            {
                               "nome": "Venezia"
                            },
                            {
                               "nome": "Treviso"
                            }
                         ],
                         "regione": "Veneto"
                      },
                      {
                         "province": [
                            {
                               "comuni": [
                                  {
                                     "nome": "Varmo",
                                     "parziale": false
                                  }
                               ],
                               "nome": "Udine"
                            }
                         ],
                         "regione": "Friuli venezia giulia"
                      }
                   ]
                }
             }
          ]
       }
    }
    

    所有代码都集中在一个地方:

    http://sense.qbox.io/gist/3b187e0fe22651a42501619ff867e02501b81f9e

    【讨论】:

    • 感谢重播,示例查询工作正常。仍然有一些更复杂的数据的结果让我觉得我没有很好地得到嵌套的东西。
    • 例如,如果我们在带有 regione:Veneto 的对象中的 nome:Treviso 附近添加一个 comuni 字段 (nome:Treviso2) 并用作查询参数 veneto, venezia 和 xxx 即使即使使用 treviso2 而不是 xxx 时,province=venezia 下的 comuni 字段为空,即使 treviso2 不在 venezia 下而是在 treviso 下,也会返回记录。也许查询正在查找父字段?我想要得到的是,如果上层匹配所有嵌套层必须与上层匹配对象匹配。
    猜你喜欢
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多