use of org.immutables.criteria.expression.Path 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.Path 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.Path in project immutables by immutables.
the class CriteriaContext method appendPath.
/**
* adds an intermediate path to partial expression
*/
public <T> CriteriaContext appendPath(Class<?> type, String pathAsString, CriteriaCreator<T> creator) {
final Member member = memberLookup.find(type, pathAsString).orElseThrow(() -> new IllegalArgumentException(String.format("Path %s not found in %s", pathAsString, type)));
Path newPath;
Expression partial = state.partial();
if (partial == null) {
newPath = Path.ofMember(member);
} else if (partial instanceof Path) {
newPath = Visitors.toPath(partial).append(member);
} else {
throw new IllegalStateException("Partial expression is not a path: " + partial);
}
return new CriteriaContext(this, state.withPartial(newPath).withCreator(creator));
}
use of org.immutables.criteria.expression.Path in project immutables by immutables.
the class CriteriaContext method any.
/**
* Build {@link IterableMatcher#any()} sub-matcher.
*/
public CriteriaContext any() {
Path path = path();
// new path starts at this root
Class<?> newType;
try {
newType = (Class<?>) Matchers.iterableTypeArgument(path.returnType());
} catch (IllegalArgumentException | ClassCastException e) {
throw new IllegalArgumentException(String.format("At path %s for %s", path.toStringPath(), path.returnType()), e);
}
Path newPath = Path.ofClass(newType);
Combiner combiner = ((left, right) -> Expressions.binaryCall(IterableOperators.ANY, path, right));
return new CriteriaContext(previous, state.withCombiner(combiner).withPartial(newPath));
}
use of org.immutables.criteria.expression.Path in project immutables by immutables.
the class MatchersTest method projection.
@Test
void projection() {
Expression expr1 = Matchers.toExpression(PersonCriteria.person.fullName);
check(expr1 instanceof Path);
check(((Path) expr1).toStringPath()).is("fullName");
Expression expr2 = Matchers.toExpression(PersonCriteria.person.bestFriend.value().hobby);
check(expr2 instanceof Path);
check(((Path) expr2).toStringPath()).is("bestFriend.hobby");
}
Aggregations