use of org.immutables.criteria.expression.Expression in project immutables by immutables.
the class AggregateQueryBuilder method jsonQuery.
ObjectNode jsonQuery() {
if (!query.groupBy().isEmpty() && query.offset().isPresent()) {
String message = "Currently ES doesn't support generic pagination " + "with aggregations. You can still use LIMIT keyword (without OFFSET). " + "For more details see https://github.com/elastic/elasticsearch/issues/4915";
throw new UnsupportedOperationException(message);
}
final ObjectNode json = nodeFactory.objectNode();
json.put("_source", false);
json.put("size", 0);
// avoid fetch phase
json.put("stored_fields", "_none_");
query.filter().ifPresent(f -> json.set("query", Elasticsearch.constantScoreQuery(mapper, pathNaming, idPredicate).convert(f)));
// due to ES aggregation format. fields in "order by" clause should go first
// if "order by" is missing. order in "group by" is un-important
final Set<Expression> orderedGroupBy = new LinkedHashSet<>();
orderedGroupBy.addAll(query.collations().stream().map(Collation::expression).collect(Collectors.toList()));
orderedGroupBy.addAll(query.groupBy());
// construct nested aggregations node(s)
ObjectNode parent = json.with(AGGREGATIONS);
for (Expression expr : orderedGroupBy) {
final String name = ((Path) expr).toStringPath();
final String aggName = naming.apply(expr);
final ObjectNode section = parent.with(aggName);
final ObjectNode terms = section.with("terms");
terms.put("field", name);
mapping.missingValueFor(name).ifPresent(m -> {
// expose missing terms. each type has a different missing value
terms.set("missing", m);
});
query.limit().ifPresent(limit -> terms.put("size", limit));
query.collations().stream().filter(c -> c.path().toStringPath().equals(name)).findAny().ifPresent(col -> terms.with("order").put("_key", col.direction().isAscending() ? "asc" : "desc"));
parent = section.with(AGGREGATIONS);
}
for (Expression expr : query.projections()) {
if (Visitors.isAggregationCall(expr)) {
Call call = Visitors.toCall(expr);
ObjectNode agg = nodeFactory.objectNode();
String field = ((Path) call.arguments().get(0)).toStringPath();
agg.with(toElasticAggregate(call)).put("field", field);
parent.set(naming.apply(call), agg);
}
}
// cleanup json. remove empty "aggregations" element (if empty)
removeEmptyAggregation(json);
return json;
}
use of org.immutables.criteria.expression.Expression in project immutables by immutables.
the class ElasticsearchQueryVisitor method visit.
@Override
public QueryBuilders.QueryBuilder visit(Call call) {
final Operator op = call.operator();
final List<Expression> args = call.arguments();
if (op == OptionalOperators.IS_PRESENT || op == OptionalOperators.IS_ABSENT) {
final String field = pathNaming.name(Visitors.toPath(args.get(0)));
QueryBuilders.QueryBuilder builder = QueryBuilders.existsQuery(field);
if (op == OptionalOperators.IS_ABSENT) {
builder = QueryBuilders.boolQuery().mustNot(builder);
}
return builder;
}
if (op == Operators.AND || op == Operators.OR) {
Preconditions.checkArgument(!args.isEmpty(), "Size should be >=1 for %s but was %s", op, args.size());
final QueryBuilders.BoolQueryBuilder builder = args.stream().map(a -> a.accept(this)).reduce(QueryBuilders.boolQuery(), (a, b) -> op == Operators.AND ? a.must(b) : a.should(b), (a, b) -> b);
return builder;
}
if (op == Operators.NOT) {
Preconditions.checkArgument(args.size() == 1, "Size should be 1 for %s but was %s", op, args.size());
final QueryBuilders.QueryBuilder builder = args.get(0).accept(this);
return QueryBuilders.boolQuery().mustNot(builder);
}
if (op.arity() == Operator.Arity.BINARY) {
return binaryCall(call);
}
throw new UnsupportedOperationException("Don't know how to handle " + call);
}
use of org.immutables.criteria.expression.Expression in project immutables by immutables.
the class Elasticsearch method idPredicate.
/**
* Predicate which checks if a path represents entity key (id). Used to generate {@code ids}
* type of queries.
*/
static Predicate<Path> idPredicate(KeyExtractor.KeyMetadata metadata) {
Objects.requireNonNull(metadata, "metadata");
Predicate<Path> alwaysFalse = p -> false;
if (!(metadata.isKeyDefined() && metadata.isExpression())) {
return alwaysFalse;
}
if (metadata.keys().size() != 1) {
return alwaysFalse;
}
Expression expression = Iterables.getOnlyElement(metadata.keys());
return Visitors.maybePath(expression).map(p -> ((Predicate<Path>) p::equals)).orElse(alwaysFalse);
}
use of org.immutables.criteria.expression.Expression in project immutables by immutables.
the class GeodeQueryVisitor method visit.
@Override
public Oql visit(Call call) {
final Operator op = call.operator();
final List<Expression> args = call.arguments();
if (op == Operators.NOT_IN || op == IterableOperators.NOT_EMPTY) {
// convert "foo not in [1, 2, 3]" into "not (foo in [1, 2, 3])"
return visit(Expressions.not(Expressions.call(inverseOp(op), call.arguments())));
}
if (op == Operators.AND || op == Operators.OR) {
Preconditions.checkArgument(!args.isEmpty(), "Size should be >=1 for %s but was %s", op, args.size());
final String join = ") " + op.name() + " (";
final String newOql = "(" + args.stream().map(a -> a.accept(this)).map(Oql::oql).collect(Collectors.joining(join)) + ")";
return new Oql(variables, newOql);
}
if (op.arity() == Operator.Arity.BINARY) {
return binaryOperator(call);
}
if (op.arity() == Operator.Arity.UNARY) {
return unaryOperator(call);
}
throw new UnsupportedOperationException("Don't know how to handle " + call);
}
use of org.immutables.criteria.expression.Expression in project immutables by immutables.
the class GeodeQueryVisitor method unaryOperator.
/**
* Operator with single operator: {@code NOT}, {@code IS_PRESENT}
*/
private Oql unaryOperator(Call call) {
final Operator op = call.operator();
final List<Expression> args = call.arguments();
Preconditions.checkArgument(args.size() == 1, "Size should be == 1 for unary operator %s but was %s", op, args.size());
Expression arg0 = args.get(0);
String path = arg0.accept(this).oql();
if (op instanceof OptionalOperators) {
// use IS_DEFINED / IS_UNDEFINED functions
String expr;
if (op == OptionalOperators.IS_PRESENT) {
expr = String.format("is_defined(%s) AND %s != null", path, path);
} else {
expr = String.format("is_undefined(%s) OR %s = null", path, path);
}
return oql(expr);
} else if (op == Operators.NOT) {
return oql(String.format("NOT (%s)", path));
} else if (op == IterableOperators.IS_EMPTY || op == StringOperators.TO_LOWER_CASE || op == StringOperators.TO_UPPER_CASE) {
return oql(String.format("%s.%s()", path, toMethodName(op)));
}
throw new UnsupportedOperationException("Unknown unary operator " + call);
}
Aggregations