通过子文档查询父文档

has_child 的查询和过滤可以通过子文档的内容来查询父文档。例如,我们根据如下查询,可查出所有80后员工所在的分公司:

  1. GET /company/branch/_search
  2. {
  3. "query": {
  4. "has_child": {
  5. "type": "employee",
  6. "query": {
  7. "range": {
  8. "dob": {
  9. "gte": "1980-01-01"
  10. }
  11. }
  12. }
  13. }
  14. }
  15. }

类似于nested queryhas_child 查询可以匹配多个子文档,并且每一个子文档的评分都不同。但是由于每一个子文档都带有评分,这些评分如何规约成父文档的总得分取决于 score_mode 这个参数。该参数有多种取值策略:默认为 none ,会忽略子文档的评分,并且会给父文档评分设置为 1.0 ; 除此以外还可以设置成 avgminmaxsum

下面的查询将会同时返回 londonliverpool ,不过由于 Alice Smith 要比 Barry Smith 更加匹配查询条件,因此 london 会得到一个更高的评分。

  1. GET /company/branch/_search
  2. {
  3. "query": {
  4. "has_child": {
  5. "type": "employee",
  6. "score_mode": "max",
  7. "query": {
  8. "match": {
  9. "name": "Alice Smith"
  10. }
  11. }
  12. }
  13. }
  14. }

TIP: score_mode 为默认的 none 时,会显著地比其模式要快,这是因为Elasticsearch不需要计算每一个子文档的评分。只有当你真正需要关心评分结果时,才需要为 score_mode 设值,例如设成 avgminmaxsum

min_children 和 max_children

has_child 的查询和过滤都可以接受这两个参数:min_childrenmax_children 。 使用这两个参数时,只有当子文档数量在指定范围内时,才会返回父文档。

如下查询只会返回至少有两个雇员的分公司:

  1. GET /company/branch/_search
  2. {
  3. "query": {
  4. "has_child": {
  5. "type": "employee",
  6. "min_children": 2, (1)
  7. "query": {
  8. "match_all": {}
  9. }
  10. }
  11. }
  12. }

<1> 至少有两个雇员的分公司才会符合查询条件。

带有 min_childrenmax_children 参数的 has_child 查询或过滤,和允许评分的 has_child 查询的性能非常接近。

has_child Filter

has_child 查询和过滤在运行机制上类似,(((“has_child query and filter”, “filter”)))区别是 has_child 过滤不支持 score_mode 参数。has_child 过滤仅用于筛选内容—如内部的一个 filtered 查询—和其他过滤行为类似:包含或者排除,但没有进行评分。

has_child 过滤的结果没有被缓存,但是 has_child 过滤内部的过滤方法适用于通常的缓存规则。