仅当存在嵌套映射时如何应用过滤器

How to apply filter only if nested mapping exists

我正在尝试在嵌套 ES 查询上应用位置半径,但嵌套值并非始终存在导致异常

"[nested] nested object under path [contact.address] is not of nested type"

我尝试检查 属性 是否存在然后应用过滤器,但到目前为止没有任何效果

映射如下:

{
  "records": {
    "mappings": {
      "user": {
        "properties": {
          "user_id": {
            "type": "long"
          },
          "contact": {
            "properties": {
              "address": {
                "properties": {
                  "city": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  },
                  "location": {
                    "properties": {
                      "lat": {
                        "type": "long"
                      },
                      "lng": {
                        "type": "long"
                      },
                      "lon": {
                        "type": "text",
                        "fields": {
                          "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                          }
                        }
                      }
                    }
                  }
              },
              "email": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "name": {
                "properties": {
                  "first_name": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  },
                  "last_name": {
                    "type": "text",
                    "fields": {
                      "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                      }
                    }
                  }
                }
              }
            }
          },
          "created_at": {
            "type": "date"
          }
        }
      }
    }
  }
}

有时记录没有位置或地址数据,这会出现问题。示例记录:

{
   "contact": {
      "name": {
        "first_name": "Test",
        "last_name": "User"
       },
        "email": "test@user.com",
        "address": {}
    },
    "user_id": 532188
}

这是我正在尝试的:

GET records/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "contact.address"
          }
        },
        {
          "exists": {
            "field": "contact.address.location"
          }
        }
      ],
      "minimum_should_match": 1,
      "should": [
        {
          "bool": {
            "filter": {
              "nested": {
                "ignore_unmapped": true,
                "path": "contact.address",
                "query": {
                  "geo_distance": {
                    "distance": "50mi",
                    "contact.address.location": {
                      "lat": 51.5073509,
                      "lon": -0.1277583
                    }
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}

您需要使用 nested 数据类型定义正确的映射以避免此问题,看起来动态映射正在产生一些问题。

我用 nested 数据类型定义了自己的映射,即使我错过了嵌套字段中的一些数据,它也不会抱怨。

索引定义

{
    "mappings": {
        "properties": {
            "user_id": {
                "type": "long"
            },
            "contact": {
                "type": "nested"
            }
        }
    }
}

索引示例文档

{
   "contact": {
      "name": {
        "first_name": "raza",
        "last_name": "ahmed"
       },
        "email": "opster@user.com",
        "address" :{ --> note empty nested field
        }

    },
    "user_id": 123456
}

用嵌套字段中的数据索引另一个文档

{
   "contact": {
      "name": {
        "first_name": "foo",
        "last_name": "bar"
       },
        "email": "opster@user.com",
        "address": {
            "location" :{. --> note nested data as well
                "lat" : 51.5073509,
                "lon" : -0.1277583
            }
        }
    },
    "user_id": 123456
}

索引另一个文档,它甚至没有空 nested 数据

{
   "contact": {
      "name": {
        "first_name": "foo",
        "last_name": "bar"
       },
        "email": "opster@user.com"
    },
    "user_id": 123456
}

使用 nested 字段搜索查询

{
    "query": {
        "nested": {
            "path": "contact", --> note this
            "query": {
                "bool": {
                    "must": [
                        {
                            "exists": {
                                "field": "contact.address"
                            }
                        },
                        {
                            "exists": {
                                "field": "contact.name.first_name"
                            }
                        }
                    ]
                }
            }
        }
    }
}

搜索结果不会抱怨不包含嵌套文档的文档(给您带来问题的查询)

"hits": [
      {
        "_index": "nested",
        "_type": "_doc",
        "_id": "3",
        "_score": 2.0,
        "_source": {
          "contact": {
            "name": {
              "first_name": "foo",
              "last_name": "bar"
            },
            "email": "opster@user.com",
            "address": { --> note the nested doc
              "location": {
                "lat": 51.5073509,
                "lon": -0.1277583
              }
            }
          },
          "user_id": 123456
        }
      }