Skip to content

Commit

Permalink
datastore: improve MongoDB facets for arrays by using unwind, #TASK-7…
Browse files Browse the repository at this point in the history
…151, #TASK-7134
  • Loading branch information
jtarraga committed Jan 16, 2025
1 parent ac66d66 commit 421d5ce
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public FacetField(String name, long count, List<Bucket> buckets) {
this.buckets = buckets;
}

public FacetField(String name, long count, String aggregationName, List<Double> aggregationValues) {
this.name = name;
this.count = count;
this.aggregationName = aggregationName;
this.aggregationValues = aggregationValues;
}

public FacetField(String name, String aggregationName, List<Double> aggregationValues) {
this.name = name;
this.aggregationName = aggregationName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ public List<FacetField> convertToDataModelType(Document document) {
} else {
fieldValues.add(documentValue.getDouble(accumulator.name()));
}
facets.add(new FacetField(documentValue.getString(INTERNAL_ID), accumulator.name(), fieldValues));
long count = 0;
if (documentValue.containsKey("count")) {
count = Long.valueOf(documentValue.getInteger("count"));
}
facets.add(new FacetField(documentValue.getString(INTERNAL_ID), count, accumulator.name(), fieldValues));
break;
}
default: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ public static List<Bson> createFacet(Bson query, String facetField) {
private static List<Bson> createFacet(Bson query, List<String> facetFields) {
List<Facet> facetList = new ArrayList<>();
Set<String> includeFields = new HashSet<>();
List<Bson> unwindList = new ArrayList<>();

// For each facet field passed we will create a MongoDB facet, thre are 4 types of facets:
// 1. Facet combining fields with commas. In this case, only 'count' is supported as accumulator.
Expand Down Expand Up @@ -739,8 +740,11 @@ private static List<Bson> createFacet(Bson query, List<String> facetFields) {
double start = Double.parseDouble(matcher1.group(2));
double end = Double.parseDouble(matcher2.group(1));
double step = Double.parseDouble(matcher2.group(2));
for (double i = start; i <= end; i += step) {
boundaries.add(i);
int numSections = (int) Math.ceil((end - start + 1) / step);
double boundary = start;
for (int i = 0; i < numSections + 1; i++) {
boundaries.add(boundary);
boundary += step;
}
} else {
throw new IllegalArgumentException(INVALID_FORMAT_MSG + facetField + RANGE_FORMAT_MSG);
Expand Down Expand Up @@ -769,6 +773,17 @@ private static List<Bson> createFacet(Bson query, List<String> facetFields) {

// Get MongoDB facet
facet = getMongoDBFacet(groupField, accumulator, accumulatorField, boundaries);

// Unwind in any case
String[] split = groupField.split("\\.");
String acc = "";
for (String s : split) {
if (!StringUtils.isEmpty(acc)) {
acc += ".";
}
acc += s;
unwindList.add(Aggregates.unwind("$" + acc));
}
}

// Add facet to the list of facets to be executed
Expand All @@ -777,14 +792,19 @@ private static List<Bson> createFacet(Bson query, List<String> facetFields) {
}
}

// Build MongoDB pipeline for facets
Bson match = Aggregates.match(query);
Bson project = Aggregates.project(Projections.include(new ArrayList<>(includeFields)));
// Dot notation management for facets
Document aggregates = GenericDocumentComplexConverter
.replaceDots(Document.parse(Aggregates.facet(facetList).toBsonDocument().toJson()));

return Arrays.asList(match, project, aggregates);
// Build and return the MongoDB pipeline for facets: match, project, [unwind,] aggregates
List<Bson> result = new ArrayList<>();
// 1 - Match
result.add(Aggregates.match(query));
// 2 - Project
result.add(Aggregates.project(Projections.include(new ArrayList<>(includeFields))));
// 3 - Unwind
if (!unwindList.isEmpty()) {
result.addAll(unwindList);
}
// 4 - Aggregates (dot notation management for facets)
result.add(GenericDocumentComplexConverter.replaceDots(Document.parse(Aggregates.facet(facetList).toBsonDocument().toJson())));
return result;
}

private static Facet getMongoDBFacet(String groupField, Accumulator accumulator, String accumulatorField, List<Double> boundaries) {
Expand Down
Loading

0 comments on commit 421d5ce

Please sign in to comment.