Aggregations
Elasticmagic DSL allows you to define aggregations on any complexity.
How it works
Aggregations
Basic API
To start writing aggregations we can reuse LaptopDoc
from Querying page.
import {Doc,Field,StringType,IntegerType,DateType,BooleanType,FloatType,} from 'elasticmagic';class LaptopDoc extends Doc {public static docType: string = 'laptop';public static model = new Field(StringType, 'model', Laptop);public static cpu = new Field(IntegerType, 'cpu', Laptop);public static price = new Field(FloatType, 'price', Laptop);public static manufacturerId = new Field(IntegerType, 'manufacturer_id', Laptop);public static manufacturedAt = new Field(DateType, 'manufactured_at', Laptop);public static forGames = new Field(BooleanType, 'for_games', Laptop);public model?: string;public cpu?: number;public price?: number;public manufactured_id?: number;public manufactured_at?: string; // ISO format stringpublic for_games?: boolean;}
SearchQuery
instance has a .aggregations()
(with short alias .aggs()
) method.
It accepts object where key is a name of aggregation and value can be one of expressions:
agg.Terms
Start wrinting aggregations
Conventionaly, you can import all aggregation related stuff as:
TODO - test this code and decide
import * as aggs from 'elasticmagic/aggs';// orimport { aggs } from 'elasticmagic';
Lets add some aggregations.
Suppose we want to get an aggregated list of prices.
First we filter docs by manufacturerIds
list.
Then we create aggregation on LaptopDoc.price
field, which means we want to collect (aggregate) prices for that manufacturers laptops.
Also we are specifying nested aggregation named forGames
- it represents amount laptops which are suited for gaming.
import {Doc,Field,StringType,IntegerType,DateType,BooleanType,FloatType,Bool,} from 'elasticmagic';import * as aggs from 'elasticmagic/aggs';const manufacturerIds = [1, 2, 3];const query = new SearchQuery().limit(0).source(false).filter(LaptopDoc.manufacturedId.in(manufacturerIds)).aggregations({prices: new aggs.Terms({field: LaptopDoc.price,/*** if actual size of matched docs is unknown at the moment of building the query,* we can set some big value, such as 10 ** 4*/size: 10 ** 4,aggs: {forGames: new aggs.Filter({filter: LaptopDoc.forGames.eq(true),})}})});const result = await qeury.getResult<LaptopDoc>();const pricesBucket = result.getAggregation('prices');const priceBucket = pricesBucket[0];console.log(priceBucket.key); // prints priceconst forGamesBucket = priceBucket.getAggregation('forGames');console.log(forGamesBucket.docCount); // prints laptops amount suited for gaming
We calling .limit(0)
to say we do not need elasticsearch to limit our query.
Also we calling .source(false)
to say we do not need elasticsearch to include source of docs in response.
As you can see, its pretty easy and straitforward to write an aggregations.