opq
Node.js client library for constructing OpenSearch query.
Installation
npm install @diotoborg/consequatur-velit-quae
Quick Start
Constructing queries for OpenSearch index has never been this simplified. opq provides queries that can be used to construct simple, complex and custom JSON queries for OpenSearch.
See example: match.js
const { pipeline, query } = require('@diotoborg/consequatur-velit-quae');
const pipelineQ = pipeline(
query.match('customer_first_name', 'Sonya'),
query.withQuery(),
);
console.log(pipelineQ());
$ node match.js
{ query: { match: { customer_first_name: [Object] } } }
Here's a more complete query based on Paginate results documentation from OpenSeach using several query from opq and pretty printing the output.
See example: paginate.js
const { pipeline, query } = require('@diotoborg/consequatur-velit-quae');
const paginateQ = pipeline(
query.match('play_name', 'Hamlet'),
query.withPaginate(0, 3),
query.withSort([
{
'speech_number': 'asc'
},
{
'_id': 'asc'
}
]),
query.withQuery(),
query.withPrettyPrint(),
);
paginateQ();
$ node paginate.js
{
"query": {
"match": {
"play_name": {
"query": "Hamlet"
}
},
"from": 0,
"size": 3,
"sort": [
{
"speech_number": "asc"
},
{
"_id": "asc"
}
]
}
}
More snippets can be found in the examples directory
Query
Opq exports query.*
which has several functions that can be used within pipeline
.
const { query } = require('@diotoborg/consequatur-velit-quae');
matchPrefix
This allows including the match_phrase_prefix
field which searches for documents matching the provided phrase.
See example: matchprefix.js
matchBool
This allows including the match_bool_prefix
field which analyzes the provided search string and creates a Boolean query.
See example: matchbool.js
match
This allows including the match
field to perform full-text search.
See example: match.js
multimatch
This allows including the multimatch
field to search multiple fields in the index. By default, fields
will be *
which searches the fields specified in the index query.
See example: multimatch.js
matchAll
This allows including the match_all
field that queries the entire index.
term
This allows including the term
field.
See example: array.js#L9
terms
This allows including the terms
field.
See example: array.js#L10
exists
checks if a field with a name exists.
const { query } = require('@diotoborg/consequatur-velit-quae');
const withExists = query.exists({
'name': 'created_at',
});
range
This allows to search for a range of given values in a field.
const { query } = require('@diotoborg/consequatur-velit-quae');
const withRange = query.range('created_at', {
'gte': '2023-04-01',
'lte': '2024-04-08'
});
withShould
This allows include the should
field which is equivalent to logical or
operator.
See example: match.js#L9
withMust
This allows include the must
field which is equivalent to logical and
operator.
See example: siblings.js#L10
withMustNot
This allows include the must_not
field which is equivalent to logical not
operator.
See example: array.js#L19
withBool
This allows including the bool
field that can be combined with withMustNot
, withMust
, withShould
and withFilter
.
See example: siblings.js#L11
withQuery
This allows including the query
field.
See example: array.js#L23
withFilter
This allows including the filter
field.
See example: filter.js
withPaginate
This allows including the from
and size
fields. The from
field is computed based on offset
and limit
provided.
See example: paginate.js
withHighlight
This allows including the highlight
field with option to replace the preTags
, postTags
and additional highlighting options.
See example: highlight.js
const { query } = require('@diotoborg/consequatur-velit-quae');
query.withHighlight([
{ 'email': {} },
{ 'username': {} }
], {
'pre_tags': ['<em>'],
'post_tags': ['</em>'],
'order': 'score',
'number_of_fragments': 0,
});
withSort
This allows including the sort
field with option to add flexible attributes.
See example: paginate.js#L8
withSource
This allows including the _source
field.
See example: array.js#L24
withConstant
This allows providing constant value with custom key.
See example: siblings.js#L8
withArray
This allows placing sub-queries within an array.
See example: array.js
withSiblings
This allows placing adjacent queries or sub-queries.
See example: siblings.js
withPrettyPrint
By default, prettyprint outputs composed query to console. You may change the default logger.
See example: paginate.js#L17
const { query } = require('@diotoborg/consequatur-velit-quae');
const winston = require('winston');
const logger = winston.createLogger({
transports: [
new winston.transports.Console({ level: 'warn' }),
new winston.transports.File({ filename: 'combined.log' })
],
});
query.withPrettyPrint({}, logger.info);
withScriptScore
This allows including the script_score
to change the scoring function of queried documents.
const { query } = require('@diotoborg/consequatur-velit-quae');
query.withScriptScore(
query.match('author', 'Dave')(),
{
source: `
_score * doc[params.field].value
`,
params: {
'field': 'multiplier'
}
}
);
{
'script_score': {
'query': {
'match': {
'author': {
'query': 'Dave',
. . .
}
}
},
'script': {
lang: 'painless',
source: '\n _score * doc[params.field].value\n ',
params: { 'field': 'multiplier' }
}
}
}
Pipeline
You can execute custom queries in addition to the built-in queries using pipeline
.
See example: custom.js
const { pipeline } = require('@diotoborg/consequatur-velit-quae');
const customFunction = (text) => {
return (baseQuery) => ({
...baseQuery,
'custom_attribute': text
});
};
const pipelineQ = pipeline(
query.match('fruit_name', 'Orange'),
query.withQuery(),
customFunction('custom_value'),
query.withPrettyPrint(),
);
pipelineQ();
$ node sample-custom.js
{
"query": {
"match": {
"fruit_name": {
"query": "Orange",
"operator": "OR",
"max_expansions": 30,
"boost": 1
}
}
},
"custom_attribute": "custom_value"
}
Client
Connection to OpenSearch can be initiated using newClient
. It requires at minimum host
, username
and password
but you can provide additional configuration to fine-tune the performance such as circuit breaking.
See example: client.js
const { newClient } = require('@diotoborg/consequatur-velit-quae');
const client = newClient({
host: 'localhost:9200',
username: 'admin',
password: 'admin',
enableLongNumeralSupport: true,
memoryCircuitBreakerEnabled: true,
memoryCircuitBreakerMaxPercent: 0.8,
});
You can validate configuration credentials using createCredentials
.
const { createCredentials } = require('@diotoborg/consequatur-velit-quae');
console.log(createCredentials({
host: 'localhost:9200',
username: 'admin',
password: 'admin',
protocol: 'http'
}));
Debugging
debug a tiny JavaScript debugging utility tool is used for client error and info output. The debug output can be toggled by prefix node command with DEBUG=*
for the whole module or DEBUG=opensearch:opq
for opq only output.
DEBUG=* node examples/client.js