【问题标题】:Return parent data with child document from Elasticsearch从 Elasticsearch 返回带有子文档的父数据
【发布时间】:2018-12-14 07:33:31
【问题描述】:

是否可以通过在 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
              }
            }
          }
        }
      }
    }
  }
}
  }
}

【问题讨论】:

  • 您需要更具体。为 nested 查询返回的文档确实包含“根”文档中的字段。
  • 我已经用更多信息更新了原始问题。
  • 我想知道您是否找到了答案。我正在寻找完全相同的查询。

标签: elasticsearch


【解决方案1】:

可以使用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 构建源代码并尝试一下。

【讨论】:

  • 这也是我的想法。我已经用我的“has_child”方法更新了这个问题。不幸的是,我不能使用 1.5,因为它没有发布和支持。
【解决方案2】:

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

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

结果将出现在响应的 inner_hits 中。

【讨论】:

    【解决方案3】:

    正如 Dan Tuffery 在他的评论中所说,目前,这可以通过 Inner Hits 来实现,在 Java 中,您可以通过下一个 sn-p 代码更容易地理解它。

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-16
      • 1970-01-01
      相关资源
      最近更新 更多