使用Elasticsearch中的子文档返回父数据

时间:2015-02-11 10:27:00

标签: elasticsearch

是否可以通过在Elasticsearch查询中搜索子文档来返回父数据?

我有两种文档类型,例如书和章,与父/子(非嵌套)相关。

我想对子文档运行搜索并返回子文档,其中包含父文档中的一些字段。我试图避免对父进行单独的查询。

更新

我能找到的唯一方法是使用has_child查询,然后使用一系列聚合来钻回子项并再次应用查询/过滤器。然而,这似乎过于复杂和低效。

GET index/_search
{
  "size": 10,
  "query": {
    "has_child": {
      "type": "chapter",
  "query": {
    "term": {
      "field": "value"
        }
      }
    }
  },
  "aggs": {
"name1": {
  "terms": {
    "size": 50,
    "field": "id"
  },
  "aggs": {
    "name2": {
      "top_hits": {
        "size": 50
      }
    },
    "name3": {
      "children": {
        "type": "type2"
      },
      "aggs": {
        "docFilter": {
          "filter": {
            "query": {
              "match": {
                "_all": "value"
              }
            }
          },
          "aggs": {
            "docs": {
              "top_hits": {
                "size": 50
              }
            }
          }
        }
      }
    }
  }
}
  }
}

3 个答案:

答案 0 :(得分:2)

可以执行has_child查询以返回带有top hits聚合的父文档以返回子文档,但这有点麻烦。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html

将在1.5.0中发布的Inner Hits功能可以满足您的需求。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-request-inner-hits.html

你可以从master构建源代码并试用它。

答案 1 :(得分:0)

正如Dan Tuffery在他的评论中所说,目前,这可以通过内部命中来实现,在Java中,您可以使用下一段代码更容易理解它。

SearchResponse searchResponse = this.transportClient.prepareSearch("your_index")
                .setTypes("your_type")
                .setQuery(QueryBuilders.filteredQuery(
                                null,
                                FilterBuilders.hasParentFilter(
                                        "parent_type_name",
                                        FilterBuilders.termFilter("foo", "foo"))
                                .innerHit(new QueryInnerHitBuilder()))
                )
                .execute().actionGet();

List<YourObject> list = new ArrayList<>();

for (SearchHit searchHit : searchHits.getHits()) {

    YourObject yourObject = this.objectMapper.readValue(searchHit.getSourceAsString(), YourObject.class);
    yourObject.setYourParentObject(this.objectMapper.readValue(searchHit.getInnerHits().get("parent_type_name").getAt(0).getSourceAsString(), YourParentObject.class));

    list.add(yourObject);
}

答案 2 :(得分:0)

现在可以使用ElasticSearch完成此操作。只需在搜索查询中使用“ has_parent”即可:

'has_parent': {
    'parent_type': 'book',
    'query': {
        'match_all': {}
    },
    'inner_hits': {}
}

结果将显示在响应的inner_hits中。