elasticmagic-js - JS/Typescript DSL for Elasticsearch
The project is still very much a work in progress and in an alpha state, api may/will change; input and contributions welcome!
Elasticmagic is an Elasticsearch query builder and ORM for JavaScript/Typescript.
It helps you easily build queries which are typed and safe.
You do not need to remember how to write json
DSL for Elasticsearch, Elasticmagic will do it for you.
This lib is a port of original library written in python
by @anti-social
Versions
Supports Elasticsearch version 6.x
Docs
Docs - https://elasticmagic.js.org/
Changelog - https://elasticmagic.js.org/docs/changelog.html
Installation
To install Elasticmagic via NPM:
npm install --save elasticmagic
Also you need an Elasticseach official js client
npm install --save @elastic/elasticsearch
Getting Started
Query building
import { Client } from '@elastic/elasticsearch';
import {
Cluster,
Field,
IntegerType,
Doc,
Bool,
} from "elasticmagic-js";
class OrderDoc extends Doc {
public static docType: string = 'order';
public static userId = new Field(IntegerType, 'user_id', OrderDoc);
public user_id?: number;
public static status = new Field(IntegerType, 'status', OrderDoc);
public status?: number;
public static source = new Field(IntegerType, 'source', OrderDoc);
public source?: number;
public static price = new Field(IntegerType, 'price', OrderDoc);
public price?: number;
public static dateCreated = new Field(DateType, 'date_created', OrderDoc);
public date_created?: Date;
}
const client = new Client({ node: 'http://es6-test:9200' });
const cluster = new Cluster(client, 'test_order_index');
const query = cluster.searchQuery({ routing: 1 })
.source(true)
.filter(
Bool.must(
OrderDoc.user_id.in([1]),
OrderDoc.status.in([1, 2]),
OrderDoc.source.not(1),
OrderDoc.dateCreated.lte(new Date().toISOString())
)
);
const result = await query.getResult<OrderDoc>();
console.log(result.getIds());
const hit = result.hits[0];
console.log(hit.user_id);
We can check what query Elasticmagic will build for us.
console.log(query.toJSON())
console.log(query.body)
console.log(query.prettyQuery)
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)
Tests
Run all tests
make test
Run one test
make test TEST=tests/testSearchQuery.spec.ts
make test TEST=testSearchQuery.spec.ts
TODO
Document API (CRUD)
Query DSL
Search APIs (
Elasticsearch versions interop
Development
cat APIs
Other