diff --git a/graphql/src/main/java/org/restheart/graphql/datafetchers/GQLAggregationDataFetcher.java b/graphql/src/main/java/org/restheart/graphql/datafetchers/GQLAggregationDataFetcher.java index 74890ca63f..af04c17361 100644 --- a/graphql/src/main/java/org/restheart/graphql/datafetchers/GQLAggregationDataFetcher.java +++ b/graphql/src/main/java/org/restheart/graphql/datafetchers/GQLAggregationDataFetcher.java @@ -21,9 +21,9 @@ package org.restheart.graphql.datafetchers; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; -import com.mongodb.client.AggregateIterable; import org.bson.BsonArray; import org.bson.BsonDocument; import org.restheart.configuration.Configuration; @@ -34,11 +34,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.mongodb.client.AggregateIterable; + import graphql.schema.DataFetchingEnvironment; public class GQLAggregationDataFetcher extends GraphQLDataFetcher { - private final Logger logger = LoggerFactory.getLogger(GQLAggregationDataFetcher.class); + private final Logger LOGGER = LoggerFactory.getLogger(GQLAggregationDataFetcher.class); private static final String AGGREGATION_TIME_LIMIT_KEY = "aggregation-time-limit"; private long aggregationTimeLimit; @@ -65,46 +67,43 @@ public GQLAggregationDataFetcher(AggregationMapping aggregationMapping) { } @Override - public Object get(DataFetchingEnvironment environment) throws Exception { - return CompletableFuture.supplyAsync(() -> { - var aggregation = (AggregationMapping) this.fieldMapping; - - try { - aggregation.getResolvedStagesAsList(environment); - } catch (QueryVariableNotBoundException e) { - logger.info("Something went wrong while trying to resolve stages {}", e.getMessage()); - throw new RuntimeException(e); - } + public Object get(DataFetchingEnvironment env) throws Exception { + var aggregation = (AggregationMapping) this.fieldMapping; + + try { + aggregation.getResolvedStagesAsList(env); + } catch (QueryVariableNotBoundException e) { + LOGGER.info("Something went wrong while trying to resolve stages {}", e.getMessage()); + throw new RuntimeException(e); + } + + AggregateIterable res = null; + try { + var aggregationList = aggregation.getResolvedStagesAsList(env); - AggregateIterable res = null; - try { - var aggregationList = aggregation.getResolvedStagesAsList(environment); - - // If user does not pass any stage return an empty array - if(aggregationList.size() == 0 ) { - return new BsonArray(); - } - - res = mongoClient - .getDatabase(aggregation.getDb().getValue()) - .getCollection(aggregation.getCollection().getValue()) - .withDocumentClass(BsonDocument.class) - .aggregate(aggregationList) - .allowDiskUse(aggregation.getAllowDiskUse().getValue()) - .maxTime(this.aggregationTimeLimit, TimeUnit.MILLISECONDS); - - } catch (QueryVariableNotBoundException e) { - logger.error("Aggregation pipeline has failed! {}", e.getMessage()); - e.printStackTrace(); + // If user does not pass any stage return an empty array + if(aggregationList.isEmpty() ) { + return new BsonArray(); } - var stageOutput = new ArrayList(); + res = mongoClient + .getDatabase(aggregation.getDb().getValue()) + .getCollection(aggregation.getCollection().getValue()) + .withDocumentClass(BsonDocument.class) + .aggregate(aggregationList) + .allowDiskUse(aggregation.getAllowDiskUse().getValue()) + .maxTime(this.aggregationTimeLimit, TimeUnit.MILLISECONDS); - if(res != null) { - res.forEach(doc -> stageOutput.add(doc)); - } + } catch (QueryVariableNotBoundException e) { + LOGGER.error("Field-to-aggregation mapping has failed! {}", e.getMessage(), e); + } + + var stageOutput = new ArrayList(); + + if(res != null) { + res.forEach(doc -> stageOutput.add(doc)); + } - return stageOutput; - }); + return stageOutput; } } diff --git a/graphql/src/main/java/org/restheart/graphql/datafetchers/GraphQLDataFetcher.java b/graphql/src/main/java/org/restheart/graphql/datafetchers/GraphQLDataFetcher.java index fa49957760..839471ac8c 100644 --- a/graphql/src/main/java/org/restheart/graphql/datafetchers/GraphQLDataFetcher.java +++ b/graphql/src/main/java/org/restheart/graphql/datafetchers/GraphQLDataFetcher.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * =========================LICENSE_END================================== @@ -25,7 +25,6 @@ import org.restheart.graphql.models.FieldMapping; public abstract class GraphQLDataFetcher implements DataFetcher { - protected static MongoClient mongoClient; protected FieldMapping fieldMapping; @@ -36,5 +35,4 @@ public static void setMongoClient(MongoClient mClient){ public GraphQLDataFetcher(FieldMapping fieldMapping){ this.fieldMapping = fieldMapping; } - } diff --git a/graphql/src/main/java/org/restheart/graphql/dataloaders/AggregationBatchLoader.java b/graphql/src/main/java/org/restheart/graphql/dataloaders/AggregationBatchLoader.java index bfef849ceb..0fa1f141eb 100644 --- a/graphql/src/main/java/org/restheart/graphql/dataloaders/AggregationBatchLoader.java +++ b/graphql/src/main/java/org/restheart/graphql/dataloaders/AggregationBatchLoader.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * =========================LICENSE_END================================== @@ -53,31 +53,29 @@ public static void setMongoClient(MongoClient mClient) { @Override public CompletionStage> load(List pipelines) { - return CompletableFuture.supplyAsync(() -> { - var res = new ArrayList(); + var res = new ArrayList(); - var listOfFacets = pipelines.stream() - .map(pipeline -> new Facet(String.valueOf(pipeline.hashCode()), toBson(pipeline))) - .toList(); + var listOfFacets = pipelines.stream() + .map(pipeline -> new Facet(String.valueOf(pipeline.hashCode()), toBson(pipeline))) + .toList(); - var iterable = mongoClient.getDatabase(this.db) - .getCollection(this.collection, BsonValue.class) - .aggregate(List.of(Aggregates.facet(listOfFacets))); + var iterable = mongoClient.getDatabase(this.db) + .getCollection(this.collection, BsonValue.class) + .aggregate(List.of(Aggregates.facet(listOfFacets))); - var aggResult = new BsonArray(); + var aggResult = new BsonArray(); - iterable.into(aggResult); + iterable.into(aggResult); - var resultDoc = aggResult.get(0).asDocument(); + var resultDoc = aggResult.get(0).asDocument(); - pipelines.forEach(query -> { - BsonValue queryResult = resultDoc.get(String.valueOf(query.hashCode())); - res.add(queryResult); - }); - - return res; + pipelines.forEach(query -> { + BsonValue queryResult = resultDoc.get(String.valueOf(query.hashCode())); + res.add(queryResult); }); + return CompletableFuture.completedFuture(res); + } private List toBson(BsonValue pipeline) { diff --git a/graphql/src/main/java/org/restheart/graphql/dataloaders/QueryBatchLoader.java b/graphql/src/main/java/org/restheart/graphql/dataloaders/QueryBatchLoader.java index f4b70aa629..a8c348dde1 100644 --- a/graphql/src/main/java/org/restheart/graphql/dataloaders/QueryBatchLoader.java +++ b/graphql/src/main/java/org/restheart/graphql/dataloaders/QueryBatchLoader.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * =========================LICENSE_END================================== @@ -76,57 +76,54 @@ public QueryBatchLoader(String db, String collection) { @Override public CompletionStage> load(List queries) { - return CompletableFuture.supplyAsync(() -> { - var res = new ArrayList(); - List stages = new ArrayList<>(); + var res = new ArrayList(); + List stages = new ArrayList<>(); - // if there are at least 2 queries within the batch - if (queries.size() > 1){ - var mergedCond = new BsonArray(); - var listOfFacets = new ArrayList(); + // if there are at least 2 queries within the batch + if (queries.size() > 1){ + var mergedCond = new BsonArray(); + var listOfFacets = new ArrayList(); - // foreach query within the batch... - queries.forEach(query -> { - // add find condition to merged array - BsonDocument findClause = query.asDocument().containsKey("find") ? query.asDocument().getDocument("find") : new BsonDocument(); - mergedCond.add(findClause); + // foreach query within the batch... + queries.forEach(query -> { + // add find condition to merged array + BsonDocument findClause = query.asDocument().containsKey("find") ? query.asDocument().getDocument("find") : new BsonDocument(); + mergedCond.add(findClause); - // create a new sub-pipeline with query stages - listOfFacets.add(new Facet(String.valueOf(query.hashCode()), getQueryStages(query.asDocument()))); - }); + // create a new sub-pipeline with query stages + listOfFacets.add(new Facet(String.valueOf(query.hashCode()), getQueryStages(query.asDocument()))); + }); - // 1° stage --> $match with conditions merged by $or operator - stages.add(Aggregates.match(new BsonDocument("$or", mergedCond))); + // 1° stage --> $match with conditions merged by $or operator + stages.add(Aggregates.match(new BsonDocument("$or", mergedCond))); - // 2° stage --> $facet with one sub-pipeline for each query within the batch - stages.add(Aggregates.facet(listOfFacets)); + // 2° stage --> $facet with one sub-pipeline for each query within the batch + stages.add(Aggregates.facet(listOfFacets)); - var iterable = mongoClient.getDatabase(this.db).getCollection(this.collection, BsonValue.class).aggregate(stages); + var iterable = mongoClient.getDatabase(this.db).getCollection(this.collection, BsonValue.class).aggregate(stages); - BsonArray aggResult = new BsonArray(); + BsonArray aggResult = new BsonArray(); - iterable.into(aggResult); + iterable.into(aggResult); - var resultDoc = aggResult.get(0).asDocument(); - queries.forEach(query -> { - BsonValue queryResult = resultDoc.get(String.valueOf(query.hashCode())); - res.add(queryResult); - }); - // ... otherwise merging is not needed and sub-pipelines neither - } else { - var query = queries.get(0).asDocument(); - stages = getQueryStages(query); - var iterable = mongoClient.getDatabase(this.db).getCollection(this.collection, BsonValue.class).aggregate(stages); - var aggResult = new BsonArray(); + var resultDoc = aggResult.get(0).asDocument(); + queries.forEach(query -> { + BsonValue queryResult = resultDoc.get(String.valueOf(query.hashCode())); + res.add(queryResult); + }); + // ... otherwise merging is not needed and sub-pipelines neither + } else { + var query = queries.get(0).asDocument(); + stages = getQueryStages(query); + var iterable = mongoClient.getDatabase(this.db).getCollection(this.collection, BsonValue.class).aggregate(stages); + var aggResult = new BsonArray(); - iterable.into(aggResult); + iterable.into(aggResult); - res.add(aggResult); - } - - return res; - }); + res.add(aggResult); + } + return CompletableFuture.completedFuture(res); } private List getQueryStages(BsonDocument queryDoc){