Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregations for inner hits

I have a parent-children mapping in ElasticSearch:

parent: user

children: privileges

For privileges there are a few properties, and one is "privilegeName".

The query returns users which have certain privileges, but I would like to return the aggregated privilegeNames for each user for the privileges that match the has_child query. I can return all privileges with inner_hits and process them on the client side, but that may be cumbersome. Is there a possibility to aggregate the inner_hits?

Thanks

like image 534
Adrian Ivan Avatar asked Aug 23 '15 19:08

Adrian Ivan


People also ask

What is inner hits in Elasticsearch?

The inner hits feature can be used for this. This feature returns per search hit in the search response additional nested hits that caused a search hit to match in a different scope. Inner hits can be used by defining an inner_hits definition on a nested , has_child or has_parent query and filter.

What is nested aggregation?

Nested aggregationeditA special single bucket aggregation that enables aggregating nested documents. For example, lets say we have an index of products, and each product holds the list of resellers - each having its own price for the product.

What is top hits aggregation Elasticsearch?

A top_hits metric aggregator keeps track of the most relevant document being aggregated. This aggregator is intended to be used as a sub aggregator, so that the top matching documents can be aggregated per bucket.


1 Answers

I believe what you're looking for is the Children Aggregation.

For example, let's say I create the following index with the user as the parent, and privilege as the child:

PUT /my_index
{
  "mappings": {
    "user": {
      "properties": {
        "name": {
          "type": "string"
        },
        "age": {
          "type": "integer"
        }
      }
    },
    "privilege": {
      "properties": {
        "privilegeName": {
          "type": "string"
        }
      },
      "_parent": {
        "type": "user"
      }
    }
  }
}

Then, I add the following users:

PUT /my_index/user/1
{
  "name": "sally",
  "age": 32
}

PUT /my_index/user/2
{
  "name":"bob",
  "age": 41
}

Then I give each user some privileges. Let's say I give Sally the privilege to 'add','update' and 'delete':

POST /my_index/privilege/?parent=1
{
  "privilegeName":"add"
}

POST /my_index/privilege/?parent=1
{
  "privilegeName":"update"
}

POST /my_index/privilege/?parent=1
{
  "privilegeName":"delete"
}

But I only give Bob the privilege to 'add' and 'update':

POST /my_index/privilege/?parent=2
{
  "privilegeName":"add"
}

POST /my_index/privilege/?parent=2
{
  "privilegeName":"update"
}

I can now search for all the users that have the 'add' privilege using the has_child query. But, in the aggs, I can also show a full list of all the privileges that each of the matching users has:

GET /my_index/user/_search
{
  "query": {
    "has_child": {
      "type": "privilege",
      "query": {
        "match": {
          "privilegeName": "add"
        }
      }
    }
  },
  "aggs": {
    "by_user": {
      "terms": {
        "field": "name"
      },
      "aggs": {
        "to_privs": {
          "children": {
            "type": "privilege"
          },
          "aggs": {
            "user_privs": {
              "terms": {
                "field": "privilegeName"
              }
            }
          }
        }
      }
    }
  }
}
like image 117
BrookeB Avatar answered Sep 30 '22 20:09

BrookeB