Elasticsearch Query - 返回所有没有相应文档的文档

时间:2015-07-09 13:05:05

标签: elasticsearch

我有一个索引,其中包含具有状态的文档。这些最初是通过作业导入的,其状态设置为0。

为简单起见:

{
    "_uid" : 1234
    "id" : 1
    "name" : "someName",
    "status" : 0
}

然后,另一个导入作业通过迭代status = 0的每个对象来运行并扩展这些对象。扩展的每个对象都获得状态1。

{
    "_uid" : 1234
    "id" : 1
    "name" : "someName",
    "newProperty" : "someValue",
    "status" : 1
}

(注意未改变的_uid。它是同一个对象)

现在我有第三个导入作业,它接受状态为1的所有对象,获取他们的ID(ID !!!不是他们的_uid!)并创建一个具有相同ID但不同UID的新对象:

{
    "_uid" : 5678
    "id" : 1
    "completelyDifferentProperty" : "someValue"
    "status" : 2
}

现在,对于每个ID,我有两个对象:一个状态= 1,一个状态= 2。

对于上一个工作,我需要确保它只选择status = 1的对象,它们不具有相应的status = 2对象。

所以我需要一个查询效果 "获取status == 1的所有对象,其中没有状态== 2具有相同ID的对象存在"。

我有一种感觉聚合可能会对我有所帮助,但我还没有想到它。

1 个答案:

答案 0 :(得分:1)

您可以使用parent/child relationship轻松完成。这是一种特殊情况下的功能使用,但我认为它可以用来解决你的问题。

为了测试它,我设置了一个这样的索引,parent_doc类型和child_doc类型(我只包括设置功能所需的属性;它没有&#t; t在文档中添加更多内容会受到伤害):

PUT /test_index
{
   "mappings": {
      "parent_doc": {
         "_id": {
            "path": "id"
         },
         "properties": {
            "id": {
               "type": "long"
            },
            "_uid": {
               "type": "long"
            },
            "status": {
               "type": "integer"
            }
         }
      },
      "child_doc": {
         "_parent": {
            "type": "parent_doc"
         },
         "_id": {
            "path": "id"
         },
         "properties": {
            "id": {
               "type": "long"
            },
            "_uid": {
               "type": "long"
            },
            "status": {
               "type": "long"
            }
         }
      }
   }
}

然后我添加了四个文档;三个父母,一个孩子。有一个文档"status: 1没有相应的子文档。

POST /test_index/_bulk
{"index":{"_type":"parent_doc"}}
{"_uid":1234,"id":1,"name":"someName","newProperty":"someValue","status":0}
{"index":{"_type":"parent_doc"}}
{"_uid":1234,"id":2,"name":"someName","newProperty":"someValue","status":1}
{"index":{"_type":"child_doc","_parent":2}}
{"_uid":5678,"id":2,"completelyDifferentProperty":"someValue","status":2}
{"index":{"_type":"parent_doc"}}
{"_uid":4321,"id":3,"name":"anotherName","newProperty":"anotherValue","status":1}

我们可以找到我们想要的文件;请注意,我们仅查询parent_doc类型,并且我们的条件是status1且不存在任何子项(

):

POST /test_index/parent_doc/_search
{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "bool": {
               "must": [
                  {
                     "term": {
                        "status": 1
                     }
                  },
                  {
                     "not": {
                        "filter": {
                           "has_child": {
                              "type": "child_doc",
                              "query": {
                                 "match_all": {}
                              }
                           }
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}

返回:

{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 2,
      "successful": 2,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "test_index",
            "_type": "parent_doc",
            "_id": "3",
            "_score": 1,
            "_source": {
               "_uid": 4321,
               "id": 3,
               "name": "anotherName",
               "newProperty": "anotherValue",
               "status": 1
            }
         }
      ]
   }
}

这是我用来测试它的所有代码:

http://sense.qbox.io/gist/d1a0267087d6e744b991de5cdec1c31d947ebc13