Search in sources :

Example 1 with Collation

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;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Path(org.immutables.criteria.expression.Path) Call(org.immutables.criteria.expression.Call) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) Expression(org.immutables.criteria.expression.Expression) Collation(org.immutables.criteria.expression.Collation)

Example 2 with Collation

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;
}
Also used : Path(org.immutables.criteria.expression.Path) Document(org.bson.Document) Iterables(com.google.common.collect.Iterables) ReplaceOneModel(com.mongodb.client.model.ReplaceOneModel) Path(org.immutables.criteria.expression.Path) PathNaming(org.immutables.criteria.backend.PathNaming) Projections(com.mongodb.client.model.Projections) StandardOperations(org.immutables.criteria.backend.StandardOperations) ReplaceOptions(com.mongodb.client.model.ReplaceOptions) BsonDocumentWriter(org.bson.BsonDocumentWriter) DefaultResult(org.immutables.criteria.backend.DefaultResult) MongoCollection(com.mongodb.reactivestreams.client.MongoCollection) CodecRegistry(org.bson.codecs.configuration.CodecRegistry) ExpressionNaming(org.immutables.criteria.backend.ExpressionNaming) Backend(org.immutables.criteria.backend.Backend) Function(java.util.function.Function) FlowableTransformer(io.reactivex.FlowableTransformer) BsonDocument(org.bson.BsonDocument) BsonValue(org.bson.BsonValue) Query(org.immutables.criteria.expression.Query) Level(java.util.logging.Level) FullDocument(com.mongodb.client.model.changestream.FullDocument) Bson(org.bson.conversions.Bson) ChangeStreamPublisher(com.mongodb.reactivestreams.client.ChangeStreamPublisher) Flowable(io.reactivex.Flowable) EncoderContext(org.bson.codecs.EncoderContext) WatchEvent(org.immutables.criteria.backend.WatchEvent) ProjectedTuple(org.immutables.criteria.backend.ProjectedTuple) Collation(org.immutables.criteria.expression.Collation) ExpressionConverter(org.immutables.criteria.expression.ExpressionConverter) MongoException(com.mongodb.MongoException) Publisher(org.reactivestreams.Publisher) CodecRegistries(org.bson.codecs.configuration.CodecRegistries) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) KeyExtractor(org.immutables.criteria.backend.KeyExtractor) Visitors(org.immutables.criteria.expression.Visitors) List(java.util.List) Sorts(com.mongodb.client.model.Sorts) BulkWriteResult(com.mongodb.bulk.BulkWriteResult) UniqueCachedNaming(org.immutables.criteria.backend.UniqueCachedNaming) FindPublisher(com.mongodb.reactivestreams.client.FindPublisher) Codec(org.bson.codecs.Codec) WriteResult(org.immutables.criteria.backend.WriteResult) Optional(java.util.Optional) BackendException(org.immutables.criteria.backend.BackendException) ExpressionNaming(org.immutables.criteria.backend.ExpressionNaming) Query(org.immutables.criteria.expression.Query) Collation(org.immutables.criteria.expression.Collation) Bson(org.bson.conversions.Bson) BsonDocument(org.bson.BsonDocument) CodecRegistry(org.bson.codecs.configuration.CodecRegistry)

Aggregations

ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)1 Iterables (com.google.common.collect.Iterables)1 MongoException (com.mongodb.MongoException)1 BulkWriteResult (com.mongodb.bulk.BulkWriteResult)1 Projections (com.mongodb.client.model.Projections)1 ReplaceOneModel (com.mongodb.client.model.ReplaceOneModel)1 ReplaceOptions (com.mongodb.client.model.ReplaceOptions)1 Sorts (com.mongodb.client.model.Sorts)1 FullDocument (com.mongodb.client.model.changestream.FullDocument)1 ChangeStreamPublisher (com.mongodb.reactivestreams.client.ChangeStreamPublisher)1 FindPublisher (com.mongodb.reactivestreams.client.FindPublisher)1 MongoCollection (com.mongodb.reactivestreams.client.MongoCollection)1 Flowable (io.reactivex.Flowable)1 FlowableTransformer (io.reactivex.FlowableTransformer)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Objects (java.util.Objects)1 Optional (java.util.Optional)1 Function (java.util.function.Function)1 Level (java.util.logging.Level)1