What is it?
pandagg is a Python package providing a simple interface to manipulate ElasticSearch queries and aggregations.
Disclaimer :this is a pre-release version
Features
- flexible aggregation and search queries declaration
- query validation based on provided mapping
- parsing of aggregation results in handy formats: tree with interactive navigation, csv-like tabular breakdown, and others
- mapping interactive navigation
Usage
Documentation
Full documentation and user-guide are available here on read-the-docs.
Quick sneak peek
Elasticsearch dict syntax
>>> from pandagg.query import Query
>>> expected_query = {'bool': {'must': [
{'terms': {'genres': ['Action', 'Thriller']}},
{'range': {'rank': {'gte': 7}}},
{'nested': {
'path': 'roles',
'query': {'bool': {'must': [
{'term': {'roles.gender': {'value': 'F'}}},
{'term': {'roles.role': {'value': 'Reporter'}}}]}
}
}}
]}}
>>> q = Query(expected_query)
>>> q
<Query>
bool
└── must
├── nested
│ ├── path="roles"
│ └── query
│ └── bool
│ └── must
│ ├── term, field=roles.gender, value="F"
│ └── term, field=roles.role, value="Reporter"
├── range, field=rank, gte=7
└── terms, field=genres, values=['Action', 'Thriller']
DSL syntax
from pandagg.query import Nested, Bool, Query, Range, Term, Terms
>>> q = Query(
Bool(must=[
TermsFilter('genres', terms=['Action', 'Thriller']),
Range('rank', gte=7),
Nested(
path='roles',
query=Bool(must=[
Term('roles.gender', value='F'),
Term('roles.role', value='Reporter')
])
)
])
)
# serialized query is computed by `query_dict` method
>>> q.query_dict() == expected_query
True
Chained syntax
>>> from pandagg.query import Query, Range, Term
>>> q = Query()\
.query({'terms': {'genres': ['Action', 'Thriller']}})\
.nested(path='roles', _name='nested_roles', query=Term('roles.gender', value='F'))\
.query(Range('rank', gte=7))\
.query(Term('roles.role', value='Reporter'), parent='nested_roles')
>>> q
<Query>
bool
└── must
├── nested
│ ├── path="roles"
│ └── query
│ └── bool
│ └── must
│ ├── term, field=roles.gender, value="F"
│ └── term, field=roles.role, value="Reporter"
├── range, field=rank, gte=7
└── terms, field=genres, values=['Action', 'Thriller']
Notes:
- both DSL and dict syntaxes are accepted in
Querycompound clauses methods (query,nested,mustetc). - the last query uses the nested clause
_nameto detect where it should be inserted
Installation
pip install pandagg
Dependencies
Hard dependency: ligthtree: 0.0.2 or higher
Soft dependency: to parse aggregation results as tabular dataframe: pandas
Motivations
pandagg only focuses on read operations (queries and aggregations), a
high level python client elasticsearch-dsl already exists for ElasticSearch,
but despite many qualities, in some cases its api was not always convenient when dealing with deeply
nested queries and aggregations.
The fundamental difference between those libraries is how they deal with the tree structure of aggregation queries and their responses.
Suppose we have this aggregation structure: (types of agg don't matter). Let's call all of A, B, C, D our aggregation nodes, and the whole structure our tree.
A (Terms agg)
└── B (Filters agg)
├── C (Avg agg)
└── D (Sum agg)
Question is who has the charge of storing the tree structure (how nodes are connected)?
In elasticsearch-dsl library, each aggregation node is responsible of knowing which are its direct children.
In pandagg, all nodes are agnostic about which are their parents/children, and a tree object is in charge of storing this structure. It is thus possible to add/update/remove aggregation nodes or sub-trees in specific locations of the initial tree, thus allowing more flexible ways to build your queries.
Contributing
All contributions, bug reports, bug fixes, documentation improvements, enhancements and ideas are welcome.
Roadmap
- implement CI workflow: python2/3 tests, coverage
- nested fields: automatic handling and validation in
Queryinstances Query.query,Agg.agg,Agg.groupbymethods: allow passing oftreeinstance, in addition to currentdictandnodesyntaxes- documentation; explain challenges induced by nested
nodessyntaxes: for instance why are nested query clauses saved inchildrenattribute before tree deserialization - extend test coverage on
namedqueries serialization - evaluate interest and tradeoffs of using metaclasses like similarly to
elasticsearch-dsllibrary to declarenodeclasses - on aggregation
nodes, ensure all allowedfieldsare listed - on aggregation response
tree, useQueryDSL to compute bucket filters - package versions for different ElasticSearch versions
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file pandagg-0.0.2.tar.gz.
File metadata
- Download URL: pandagg-0.0.2.tar.gz
- Upload date:
- Size: 66.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
194c42da177f1d001385bc43766cc3d431ef9315fef2594342f8e6c8e0ace6df
|
|
| MD5 |
5b5fbd5e7dd91bd1f0be3121f3891b1c
|
|
| BLAKE2b-256 |
6572dac1e4b893b6f9d34fba047e244572827246b76f8adc0ae61a460baa3ebd
|