Elasticsearch多级嵌套查询

时间:2015-10-09 16:02:27

标签: elasticsearch

使用多级嵌套字段进行映射,如下所示:

{
  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"
      }
    ]
  }
}

即使缺少省字段,查询也找不到给定的记录,如果我们使用" Veneto"它可以正常工作。对于地区和"特雷维索"对于provincia.nome并使用另一个嵌套对象中的comune字段。

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

1 个答案:

答案 0 :(得分:0)

尝试将您的条款更改为小写。由于您未在映射中指定分析器,因此使用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