Skip to main content

final class atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender

Recommend AggregateProvider s for a Cube. The recommender analyzes the queries executed against the cube while it is recording to recommend the most impactful aggregate providers.

Example

>>> df = pd.DataFrame(
...     {
...         "Country": ["France", "France", "Germany"],
...         "City": ["Paris", "Lyon", "Berlin"],
...         "Price": [2.5, 3.0, 4.0],
...     }
... )
>>> table = session.read_pandas(df, table_name="Sales")
>>> cube = session.create_cube(table)
By default, the recommender is idle:
>>> recommender = cube.aggregate_providers.recommender
>>> recommender.status
'idle'
Recommendations require a recorded query history, so none can be made while idle:
>>> recommender.recommend(cover_target=0.42)
Traceback (most recent call last):
    ...
RuntimeError: Cannot get recommendation when status is `idle`.
Starting to record queries:
>>> recommender.status = "recording"
>>> recommender.status
'recording'
Running some queries:
>>> l, m = cube.levels, cube.measures
>>> for level in [l["City"], l["Country"]]:
...     _ = cube.query(m["Price.SUM"], levels=[level])
Getting a recommendation:
>>> import pprint
>>> recommended = recommender.recommend(
...     cover_target=0.42,
...     excluded_levels={l["Country"]},
... )
>>> pprint.pp(recommended)
{'ai-optimizer-1': AggregateProvider(filter=None,
                                     key='bitmap',
                                     levels=frozenset({l['Sales', 'City', 'City']}),
                                     measures=frozenset({m['Price.SUM']}),
                                     partitioning=None)}
Excluding another level changes the recommendation:
>>> from datetime import timedelta
>>> recommended = recommender.recommend(
...     candidate_evaluation_time_limit=timedelta(seconds=92),
...     cover_target=0.42,
...     excluded_levels={l["City"]},
... )
>>> pprint.pp(recommended)
{'ai-optimizer-1': AggregateProvider(filter=None,
                                     key='bitmap',
                                     levels=frozenset({l['Sales', 'Country', 'Country']}),
                                     measures=frozenset({m['Price.SUM']}),
                                     partitioning=None)}
Once a suitable recommendation is made, the recommender can be made idle again:
>>> recommender.status = "idle"
>>> recommender.status
'idle'
The recommendation can be applied directly:
>>> cube.aggregate_providers.update(recommended)
Or it can be serialized and transferred from one environment to another:
>>> from pydantic import TypeAdapter
>>> type_adapter = TypeAdapter(dict[str, tt.AggregateProvider])
>>> path = tmp_path / "aggregate_providers.json"
>>> _ = path.write_bytes(type_adapter.dump_json(recommended))
In another process:
>>> transferred_aggregate_providers = type_adapter.validate_json(
...     path.read_bytes()
... )
>>> recommended == transferred_aggregate_providers
True
recommendReturn recommended aggregate providers keyed by name.
statusWhether the cube records incoming queries for the recommender to analyze.