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
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.
As you can see we declare one static field and one intance field with almost same name but different types.
Static field will be used to build queries.
Instance field will be populated on search query so they must be the same as in elasticsearch document.
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 user_id?: 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 date_created?: 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: Lets suppouse we have one doc in index with id 1.
const result = await query.getResult<OrderDoc>();
console.log(result.getIds());
const hit = result.hits[0];
console.log(hit.user_id);
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
Run all tests
make test
Run one test
make test TEST=tests/testSearchQuery.spec.ts
make test TEST=testSearchQuery.spec.ts
TODO