Elasticsearch DSL python queries with filters and aggregations on nested properties

2.8k views Asked by At

I would like to build a filtered Elasticsearch query using filtering via nested objects plus make an aggregation to get the minimum value of a nested object inside a nested objects list.

The filtering part works but I can't bind it with the aggs (aggregations) part. When I add the .aggs.bucket part to my code after the filters it's either being ignored (not visible in the search.to_dict()) or gives me syntax errors.

Can anybody give me an example on how to bind those together? I'm trying to get both the filtered query result end the calculated minimum value from nested1.foo.bar in one response

Example schema:

class MyExample(DocType):
    myexample_id = Integer()
    nested1 = Nested(
        properties={
            'timestamp': Date(),
            'foo': Nested(
                properties={
                    'bar': Float(),
                }
            )
        }
    )
    nested2 = Nested(
        multi=False,
        properties={
            'x': String(),
            'y': String(),
        }
    )

Building the query:

from elasticsearch_dsl import Search, Q

search = Search().filter(
    'nested', path='nested1', inner_hits={},
    query=Q(
        'range', **{
            'nested1.timestamp': {
                'gte': exampleDate1,
                'lte': exampleDate2
            }
        }
    )
).filter(
    'nested', path='nested2', inner_hits={'name': 'x'},
    query=Q(
        'term', **{
            'nested2.x': x
        }
    )
).filter(
    'nested', path='nested2', inner_hits={'name': 'y'},
    query=Q(
        'term', **{
            'nested2.y': y
        }
    )
)

Basically what I need to do is to get the min value for all the nested nested1.foo.bar values for each unique MyExample document (they have unique myexample_id field)

1

There are 1 answers

3
Honza Král On BEST ANSWER

Adding

search.aggs\
    .bucket('nested1', 'nested', path='nested1')\
    .bucket('nested_foo', 'nested', path='nested1.foo')\
    .metric('min_bar', 'min', field='nested1.foo.bar')

on the next line should do the trick.