Elasticsearch 将范围和术语连接到同一个数组项

Elasticsearch connect range and term to same array item

我有一个用户文档,其中包含一个名为 experiences 的字段,它是一个对象数组,例如:

{
  "experiences": [
    {
      "end_date": "2017-03-02",
      "is_valid": false
    },
    {
      "end_date": "2015-03-02",
      "is_valid": true
    }
  ]
}

使用此文档,我必须搜索结束日期为去年且 is_valid 为真的用户。 此时我有一个 query -> bool 并且我在那里添加了两个 must,一个 range 用于 end_date 和一个 term 用于 is_valid.

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "experiences.is_valid": true
        },
        "range": {
          "experiences.end_date": {
            "gte": "now-1y",
            "lte": "now"
          }
        },
      }
    }
  }
}

结果是这个用户被选中是因为他在去年(第一个exp.)有一个end_date,另一个exp. is_valid 真。 当然这不是我需要的,因为我需要 end_dateis_valid 必须引用同一个对象,但我们如何在 Elasticsearch 上执行此操作?

映射:

"experiences": {
  "properties": {
    "comment": {
      "type": "text",
      "fields": {
        "keyword": {
          "type": "keyword",
          "ignore_above": 256
        }
      }
    },
    "end_date": {
      "type": "date"
    },
    "id": {
      "type": "long"
    },
    "is_valid": {
      "type": "boolean"
    },
    "start_date": {
      "type": "date"
    }
  }
}

您需要将 experiences 类型更改为 Nested data type

然后应用nested查询:

 {
 "query": {
  "nested": {
     "path": "experiences",
     "query": {
        "bool": {
           "must": [
              {
                 "term": {
                    "experiences.is_valid": true
                 }
              },
              {
                 "range": {
                    "experiences.end_date": {
                       "gte": "now-1y",
                       "lte": "now"
                    }
                 }
              }
           ]
        }
     }
   }
  }
 }

这是由于 Elasticsearch 中对象数组的扁平化方式所致。 多学习here