use of org.immutables.criteria.expression.Collation 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.Collation in project immutables by immutables.
the class MongoSession method query.
private Publisher<?> query(StandardOperations.Select select) {
final Query query = select.query();
final boolean hasProjections = query.hasProjections();
boolean useAggregationPipeline = query.hasAggregations() || query.distinct() || query.count() && query.limit().isPresent();
ExpressionNaming expressionNaming = useAggregationPipeline ? ExpressionNaming.from(UniqueCachedNaming.of(query.projections())) : expression -> pathNaming.name((Path) expression);
MongoCollection<?> collection = this.collection;
if (hasProjections) {
// add special TupleCodecProvider for projections
CodecRegistry newRegistry = CodecRegistries.fromRegistries(this.collection.getCodecRegistry(), CodecRegistries.fromProviders(new TupleCodecProvider(query, expressionNaming)));
collection = this.collection.withDocumentClass(ProjectedTuple.class).withCodecRegistry(newRegistry);
}
if (useAggregationPipeline) {
// aggregations
AggregationQuery agg = new AggregationQuery(query, pathNaming);
if (query.count()) {
// also for empty result-set mongo does not return single(0) but empty publisher
return Flowable.fromPublisher(collection.aggregate(agg.toPipeline(), BsonDocument.class)).map(d -> d.get("count").asNumber().longValue()).defaultIfEmpty(// return Single.just(0) for empty publisher
0L);
}
return collection.aggregate(agg.toPipeline(), ProjectedTuple.class);
}
Bson filter = toBsonFilter(query);
if (query.count()) {
// simple form of count all (without distinct, aggregations etc.) : count(*)
return Flowable.fromPublisher(collection.countDocuments(filter));
}
final FindPublisher<?> find = collection.find(filter);
if (!query.collations().isEmpty()) {
// add sorting
final Function<Collation, Bson> toSortFn = col -> {
final String path = col.path().toStringPath();
return col.direction().isAscending() ? Sorts.ascending(path) : Sorts.descending(path);
};
final List<Bson> sorts = query.collations().stream().map(toSortFn).collect(Collectors.toList());
find.sort(Sorts.orderBy(sorts));
}
query.limit().ifPresent(limit -> find.limit((int) limit));
query.offset().ifPresent(offset -> find.skip((int) offset));
if (hasProjections) {
List<String> fields = query.projections().stream().map(p -> pathNaming.name((Path) p)).collect(Collectors.toList());
find.projection(Projections.include(fields));
return find;
}
// post-process result with projections
return find;
}
Aggregations