@opra/elastic
Version:
Opra Elastic Search adapter package
131 lines (130 loc) • 4.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = prepareFilter;
require("@opra/core");
const common_1 = require("@opra/common");
function prepareFilter(filters) {
const filtersArray = Array.isArray(filters) ? filters : [filters];
if (!filtersArray.length)
return;
const out = [];
for (const filter of filtersArray) {
if (!filter)
continue;
let x = filter;
if (typeof filter === 'string')
x = prepareFilterAst(common_1.OpraFilter.parse(filter));
else if (filter instanceof common_1.OpraFilter.Expression)
x = prepareFilterAst(filter);
out.push(x);
}
if (out.length > 1) {
return { bool: { must: [...out] } };
}
return out[0] ? out[0] : undefined;
}
function prepareFilterAst(ast, negative) {
if (!ast)
return;
if (ast instanceof common_1.OpraFilter.QualifiedIdentifier ||
ast instanceof common_1.OpraFilter.Literal) {
return ast.value;
}
if (ast instanceof common_1.OpraFilter.ArrayExpression) {
return ast.items.map(x => prepareFilterAst(x, negative));
}
if (ast instanceof common_1.OpraFilter.NegativeExpression) {
return prepareFilterAst(ast.expression, !negative);
}
if (ast instanceof common_1.OpraFilter.LogicalExpression) {
const items = ast.items
.map(x => prepareFilterAst(x))
/** Filter nullish items */
.filter(x => x != null);
const k = (ast.op === 'or' ? 'should' : 'must') + (negative ? '_not' : '');
return { bool: { [k]: items } };
}
if (ast instanceof common_1.OpraFilter.ParenthesizedExpression) {
return prepareFilterAst(ast.expression, negative);
}
if (ast instanceof common_1.OpraFilter.ComparisonExpression) {
if (!(ast.left instanceof common_1.OpraFilter.QualifiedIdentifier ||
ast.left instanceof common_1.OpraFilter.StringLiteral)) {
throw new Error('Left side of ComparisonExpression must be a QualifiedIdentifier');
}
const left = prepareFilterAst(ast.left);
const right = prepareFilterAst(ast.right);
let out;
if (right == null) {
negative = !negative;
out = { exists: { field: left } };
}
else {
if (ast.prepare) {
out = ast.prepare({
left,
right,
op: ast.op,
adapter: 'elastic',
});
}
if (!out) {
switch (ast.op) {
case '!=':
case '=':
case 'in':
case '!in': {
out = Array.isArray(right)
? { terms: { [left]: right } }
: { match: { [left]: right } };
break;
}
case '>': {
out = { range: { [left]: { gt: right } } };
break;
}
case '>=': {
out = { range: { [left]: { gte: right } } };
break;
}
case '<': {
out = { range: { [left]: { lt: right } } };
break;
}
case '<=': {
out = { range: { [left]: { lte: right } } };
break;
}
case '!like':
case 'like': {
out = {
wildcard: { [left]: { value: String(right).replace(/%/g, '*') } },
};
break;
}
case '!ilike':
case 'ilike': {
out = {
wildcard: {
[left]: {
value: String(right).replace(/%/g, '*'),
case_insensitive: true,
},
},
};
break;
}
default:
/* istanbul ignore next */
throw new TypeError(`Unknown ComparisonExpression operation (${ast.op})`);
}
}
}
if ((ast.op.startsWith('!') && !negative) ||
(!ast.op.startsWith('!') && negative)) {
return { bool: { must_not: { ...out } } };
}
return out;
}
throw new Error(`${ast.kind} is not implemented yet`);
}