elastic-builder
Version:
A JavaScript implementation of the elasticsearch Query DSL
230 lines (204 loc) • 7.33 kB
JavaScript
'use strict';
const isNil = require('lodash.isnil');
const Sort = require('./sort');
const Highlight = require('./highlight');
const { checkType, setDefault, recursiveToJSON } = require('./util');
/**
* Inner hits returns per search hit in the search response additional
* nested hits that caused a search hit to match in a different scope.
* Inner hits can be used by defining an `inner_hits` definition on a
* `nested`, `has_child` or `has_parent` query and filter.
*
* [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-inner-hits.html)
*
* @example
* const reqBody = esb.requestBodySearch().query(
* esb.nestedQuery(
* esb.matchQuery('comments.message', '[actual query]')
* ).innerHits(
* esb.innerHits().source(false).storedFields(['comments.text'])
* )
* );
*
* @param {string=} name The name to be used for the particular inner hit definition
* in the response. Useful when multiple inner hits have been defined in a single
* search request. The default depends in which query the inner hit is defined.
*/
class InnerHits {
// eslint-disable-next-line require-jsdoc
constructor(name) {
// Maybe accept some optional parameter?
this._body = {};
if (!isNil(name)) this._body.name = name;
}
/**
* The name to be used for the particular inner hit definition
* in the response. Useful when multiple inner hits have been defined in a single
* search request. The default depends in which query the inner hit is defined.
*
* @param {number} name
* @returns {InnerHits} returns `this` so that calls can be chained.
*/
name(name) {
this._body.name = name;
return this;
}
/**
* The offset from where the first hit to fetch for each `inner_hits` in the returned
* regular search hits.
*
* @param {number} from
* @returns {InnerHits} returns `this` so that calls can be chained.
*/
from(from) {
this._body.from = from;
return this;
}
/**
* The maximum number of hits to return per inner_hits.
* By default the top three matching hits are returned.
*
* @param {number} size Defaults to 10.
* @returns {InnerHits} returns `this` so that calls can be chained.
*/
size(size) {
this._body.size = size;
return this;
}
/**
* How the inner hits should be sorted per inner_hits.
* By default the hits are sorted by the score.
*
* @param {Sort} sort
* @returns {InnerHits} returns `this` so that calls can be chained.
* @throws {TypeError} If parameter `sort` is not an instance of `Sort`.
*/
sort(sort) {
checkType(sort, Sort);
setDefault(this._body, 'sort', []);
this._body.sort.push(sort);
return this;
}
/**
* Allows to add multiple sort on specific fields. Each sort can be reversed as well.
* The sort is defined on a per field level, with special field name for _score to
* sort by score, and _doc to sort by index order.
*
* @param {Array<Sort>} sorts Array of sort
* @returns {InnerHits} returns `this` so that calls can be chained.
* @throws {TypeError} If any item in parameter `sorts` is not an instance of `Sort`.
*/
sorts(sorts) {
sorts.forEach(sort => this.sort(sort));
return this;
}
/**
* Allows to highlight search results on one or more fields. The implementation
* uses either the lucene `plain` highlighter, the fast vector highlighter (`fvh`)
* or `postings` highlighter.
*
* Note: The `postings` highlighter has been removed in elasticsearch 6.0.
* The `unified` highlighter outputs the same highlighting when
* `index_options` is set to `offsets`.
*
* @param {Highlight} highlight
* @returns {InnerHits} returns `this` so that calls can be chained
*/
highlight(highlight) {
checkType(highlight, Highlight);
this._body.highlight = highlight;
return this;
}
/**
* Enables explanation for each hit on how its score was computed.
*
* @param {boolean} enable
* @returns {InnerHits} returns `this` so that calls can be chained
*/
explain(enable) {
this._body.explain = enable;
return this;
}
/**
* Allows to control how the `_source` field is returned with every hit.
* You can turn off `_source` retrieval by passing `false`.
* It also accepts one(string) or more wildcard(array) patterns to control
* what parts of the `_source` should be returned
* An object can also be used to specify the wildcard patterns for `includes` and `excludes`.
*
* @param {boolean|string|Array|Object} source
* @returns {InnerHits} returns `this` so that calls can be chained
*/
source(source) {
this._body._source = source;
return this;
}
/**
* Include specific stored fields
*
* @param {Array|string} fields
* @returns {InnerHits} returns `this` so that calls can be chained
*/
storedFields(fields) {
this._body.stored_fields = fields;
return this;
}
/**
* Computes a document property dynamically based on the supplied `Script`.
*
* @param {string} scriptFieldName
* @param {string|Script} script string or instance of `Script`
* @returns {InnerHits} returns `this` so that calls can be chained
*/
scriptField(scriptFieldName, script) {
setDefault(this._body, 'script_fields', {});
this._body.script_fields[scriptFieldName] = { script };
return this;
}
/**
* Sets given dynamic document properties to be computed using supplied `Script`s.
*
* Object should have `scriptFieldName` as key and `script` as the value.
*
* @param {Object} scriptFields Object with `scriptFieldName` as key and `script` as the value.
* @returns {InnerHits} returns `this` so that calls can be chained
*/
scriptFields(scriptFields) {
checkType(scriptFields, Object);
Object.keys(scriptFields).forEach(scriptFieldName =>
this.scriptField(scriptFieldName, scriptFields[scriptFieldName])
);
return this;
}
/**
* Allows to return the doc value representation of a field for each hit.
* Doc value fields can work on fields that are not stored.
*
* @param {Array<string>} fields
* @returns {InnerHits} returns `this` so that calls can be chained
*/
docvalueFields(fields) {
this._body.docvalue_fields = fields;
return this;
}
/**
* Returns a version for each search hit.
*
* @param {boolean} enable
* @returns {InnerHits} returns `this` so that calls can be chained.
*/
version(enable) {
this._body.version = enable;
return this;
}
/**
* Override default `toJSON` to return DSL representation for the inner hits request
*
* @override
* @returns {Object} returns an Object which maps to the elasticsearch query DSL
*/
toJSON() {
return recursiveToJSON(this._body);
}
}
module.exports = InnerHits;