elasticmagic-js (alpha)
This is alpha. Api may/will change.
JS/Typescript DSL for Elasticsearch
This lib is a port of original library written in python
by @anti-social
Supports Elasticsearch version 6.x
Getting Started
Install elasticmagic-js using npm
:
npm install elasticmagic-js
Examples
Let's get started by writing a simple query.
- Declare class. We will use it both as
query builder
and container for data from elastic
import { Client } from '@elastic/elasticsearch';
import {
Cluster,
Field,
IntegerType,
Doc,
Bool,
} from "elasticmagic-js";
enum OrderStatus {
new = 1,
paid = 2,
handled = 3,
canceled = 4,
}
enum OrderSource {
desktop = 1,
mobile = 2,
}
class OrderDoc extends Doc {
public static docType: string = 'order';
public static userId = new Field(DateType, 'user_id', OrderDoc);
public userId?: number;
public static status = new Field(DateType, 'status', OrderDoc);
public status?: number;
public static source = new Field(DateType, 'source', OrderDoc);
public source?: number;
public static price = new Field(DateType, 'price', OrderDoc);
public price?: number;
public static dateCreated = new Field(DateType, 'date_created', OrderDoc);
public dateCreated?: Date;
}
- Create elasticsearch client and pass it to Cluester
const client = new Client({ node: 'http://es6-test:9200' });
const cluster = new Cluster(client, 'test_order_index');
- Now we ready to write our query
const query = cluster.searchQuery({ routing: 1 })
.source(false)
.filter(
Bool.must(
OrderDoc.user_id.in([1]),
OrderDoc.status.in([OrderStatus.new, OrderStatus.paid]),
OrderDoc.source.not(OrderSource.mobile),
)
)
.limit(0);
console.log(query.toJSON())
It will print:
{
query: {
bool: {
filter: {
bool: {
must: [
{terms: {user_id: [1]}},
{terms: {status: [1, 2]}},
{bool: {
must_not: [
{term: {source: 2}}
]
}}
]
}
}
}
},
_source: false,
size: 0
}
- To fetch results from elasticsearch:
const result = await query.getResult<OrderDoc>();
Aggregations
const query = searchQuery
.source(false)
.filter(
Bool.must(
OrderDoc.userId.in([1]),
OrderDoc.status.in([OrderStatus.new, OrderStatus.handled, OrderStatus.paid]),
OrderDoc.source.not(OrderSource.mobile),
OrderDoc.dateCreated.lte(new Date().toISOString()),
)
)
.aggregations({
usersOrders: new agg.Terms({
field: OrderDoc.userId,
size: 1,
aggs: {
total: new agg.Filter({
filter: OrderDoc.conditionSourceDesktop(),
aggs: {
selled: new agg.Filter({
filter: Bool.must(
OrderDoc.status.in([OrderStatus.paid, OrderStatus.handled]),
),
aggs: {
paid: new agg.Filter({
filter: OrderDoc.status.eq(OrderStatus.paid)
}),
handled: new agg.Filter({
filter: OrderDoc.status.eq(OrderStatus.handled)
}),
}
}),
canceled: new agg.Filter({
filter: OrderDoc.status.eq(OrderStatus.canceled),
}),
new: new agg.Filter({
filter: OrderDoc.status.eq(OrderStatus.new)
})
}
}),
lowcost: new agg.Filter({
filter: OrderDoc.conditionLowPrice()
})
}
})
});
Now you can get aggregation data
const result = await query.getResult<OrderDoc>();
const usersOrders = result.getAggregation("usersOrders");
console.log(usersOrders.buckets[0].key)
console.log(usersOrders.buckets[0].docCount)
const total = usersOrders.buckets[0].getAggregation("total")
console.log(total.docCount)
Development
Tests
First build base image
make build
Run all tests
make test
Run one test
make test TEST=tests/testSearchQuery.spec.ts
make test TEST=testSearchQuery.spec.ts
TODO