Elasticsearch query builder for Node.js, build compatible queries with the Elasticsearch 2.x DSL. Because creating complex queries using the Query DSL is a pain.
It just builds the query
element within the search request body, the complex part. This means that fields like size
or from
must be added separately, as well as the likes of sort
.
The package can be installed as a local module, to be required in your code.
npm install es-builder
Also, it can be installed globally, ready to be used through the Node.js REPL.
npm install -g es-builder
- No production dependencies
- Can be required as a module or used in the command line
- Chainable methods
built
getter method returns a copy of the object so it can be safely passed to foreign code
It is compatible with the Elasticsearch official client library:
const eb = require('es-builder');
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'localhost:9200',
log: 'trace'
});
const query = eb.QueryBuilder()
.query(eb.TermQuery('name', 'Kirby'))
.query(eb.MatchQuery('description', 'Pink, fluffy and very hungry'))
.queryMustNot(eb.TermQuery('name', 'Waddle Dee'));
// stringifying the object will give the following result
// JSON.stringify(query)
// {
// "bool": {
// "must": [{
// "term": {
// "name": "Kirby"
// }
// }, {
// "match": {
// "description": {
// "query": "Pink, fluffy and very hungry"
// }
// }
// }],
// "must_not": {
// "term": {
// "name": "Waddle Dee"
// }
// }
// }
// }
// but the created query can be passed without doing stringify, since the Elasticsearch client will stringify it internally after
client.search({
index: 'games',
type: 'dreamland',
body: {
query: query
}
}, function(err, resp) {
// result of the search here
...
});
All the query classes have been exposed to the REPL so they can be called directly.
$ es-builder
es-builder> query = QueryBuilder().query(TermQuery('name', 'Kirby')).query(MatchQuery('description', 'Pink, fluffy and very hungry')).queryMustNot(TermQuery('name', 'Waddle Dee'));
es-builder> query.stringified
'{"bool":{"must":[{"term":{"name":{"value":"Kirby"}}},{"match":{"description":{"query":"Pink, fluffy and very hungry"}}}],"must_not":{"term":{"name":{"value":"Waddle Dee"}}}}}'
es-builder> .exit
Copy the result above and paste it in your curl search request:
$ curl -XGET 'http://localhost:9200/games/dreamland/_search' -d'
{
"query" : {"bool":{"must":[{"term":{"name":{"value":"Kirby"}}},{"match":{"description":{"query":"Pink, fluffy and very hungry"}}}],"must_not":{"term":{"name":{"value":"Waddle Dee"}}}}}
}'
Adding clauses to filter context is possible as well:
query.filter(eb.TermQuery('name', 'Kirby'));
// stringifying the object will give the following result
// JSON.stringify(query)
// {
// "bool": {
// "filter": {
// "term": {
// "name": "Kirby"
// }
// }
// }
// }
There is a shortcut available for leaf query clauses when used as a local module, inspired by elasticsearch-dsl-py:
const Q = eb.Q;
const TermsQuery = eb.TermsQuery;
// doing this
Q('terms', 'name', ['Kirby', 'Metaknight']);
// equals
TermsQuery('name', ['Kirby', 'Metaknight'])
// both giving the same result:
// {
// "terms": {
// "name": ["Kirby", "Metaknight"]
// }
// }
Also, there is a one-to-one mapping relation between the raw query and its equivalent in the DSL, therefore adding directly raw queries as Javascript objects is fine.
const eb = require('es-builder');
eb.QueryBuilder().query({ terms: name: ['Kirby', 'Metaknight'] }).built;
// same result:
//
// {
// bool: {
// must: {
// terms: {
// name: [ 'Kirby', 'Metaknight' ]
// }
// }
// }
// }
// }
Combined queries can be built nesting compound query clauses.
const eb = require('es-builder');
const Q = eb.Q;
const query = eb.QueryBuilder();
// add a couple of filters
query
.filter(Q('terms', 'name', ['Kirby', 'Metaknight']))
.filter(Q('exists', 'age'));
// create a bool compound query
const boolQuery = eb.BoolQuery()
.should(Q('range', 'age').gt(20).lt(25))
.should(Q('prefix', 'surname', 'Ki'));
// nest it
query.filter(boolQuery);
// stringifying the object will give the following result
// JSON.stringify(query)
// {
// "bool": {
// "filter": {
// bool: {
// "must": [{
// "terms": {
// "name": {
// "value": ["Kirby", "Metaknight"]
// }
// }
// }, {
// "exists": {
// "field": "age"
// }
// }, {
// "bool": {
// "should": [{
// "range": {
// "age": { "gt": 20, "lt": 25 }
// }
// }, {
// "prefix": {
// "surname": {
// "value": "Ki"
// }
// }
// }]
// }
// }]
// }
// }
// }
// }
There are aliases available for some methods.
const queryBuilder = eb.QueryBuilder();
queryBuilder.query()
→queryBuilder.queryAnd()
queryBuilder.queryMustNot()
→queryBuilder.queryNot()
queryBuilder.queryShould()
→queryBuilder.queryOr()
queryBuilder.filter()
→queryBuilder.filterAnd()
queryBuilder.filterMustNot()
→queryBuilder.filterNot()
queryBuilder.filterShould()
→queryBuilder.filterOr()
const boolQuery = eb.BoolQuery();
boolQuery.must()
→boolQuery.and()
boolQuery.mustNot()
→boolQuery.not()
boolQuery.should()
→boolQuery.or()
Coming soon.
At the moment you can take a look to the tests to see how all the methods work.
- Compatible with Elasticsearch 2.x search API
- Node.js version
- As a required module: It has been transpiled to ES5 using Babel, so it is compatible with old Node.js versions (> 0.12.0)
- As a global module (REPL): > 6.0.0
- Add leaf query clauses like
multi_match
orfuzzy
- Add compound query clauses like
constant_score
ordis_max
- Allow passing array of filter objects in compound query clauses
- Browser compatible
- And more
Pull requests or any comments are more than welcome.