Skip to content

Commit bcb63b2

Browse files
mp911dechristophstrobl
authored andcommitted
DATAMONGO-1552 - Add $facet aggregation stage.
Original Pull Request: #426
1 parent 2c4377c commit bcb63b2

File tree

6 files changed

+546
-59
lines changed

6 files changed

+546
-59
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java

Lines changed: 24 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
2828
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
2929
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
30+
import org.springframework.data.mongodb.core.aggregation.FacetOperation.FacetOperationBuilder;
3031
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
3132
import org.springframework.data.mongodb.core.aggregation.GraphLookupOperation.StartWithBuilder;
3233
import org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplaceRootDocumentOperationBuilder;
@@ -68,7 +69,7 @@ public class Aggregation {
6869
*/
6970
public static final String CURRENT = SystemVariable.CURRENT.toString();
7071

71-
public static final AggregationOperationContext DEFAULT_CONTEXT = new NoOpAggregationOperationContext();
72+
public static final AggregationOperationContext DEFAULT_CONTEXT = AggregationOperationRenderer.DEFAULT_CONTEXT;
7273
public static final AggregationOptions DEFAULT_OPTIONS = newAggregationOptions().build();
7374

7475
protected final List<AggregationOperation> operations;
@@ -460,6 +461,25 @@ public static BucketAutoOperation bucketAuto(AggregationExpression groupByExpres
460461
return new BucketAutoOperation(groupByExpression, buckets);
461462
}
462463

464+
/**
465+
* Creates a new {@link FacetOperation}.
466+
*
467+
* @return
468+
*/
469+
public static FacetOperation facet() {
470+
return FacetOperation.EMPTY;
471+
}
472+
473+
/**
474+
* Creates a new {@link FacetOperationBuilder} given {@link Aggregation}.
475+
*
476+
* @param aggregationOperations the sub-pipeline, must not be {@literal null}.
477+
* @return
478+
*/
479+
public static FacetOperationBuilder facet(AggregationOperation... aggregationOperations) {
480+
return facet().and(aggregationOperations);
481+
}
482+
463483
/**
464484
* Creates a new {@link LookupOperation}.
465485
*
@@ -551,26 +571,7 @@ public static AggregationOptions.Builder newAggregationOptions() {
551571
*/
552572
public DBObject toDbObject(String inputCollectionName, AggregationOperationContext rootContext) {
553573

554-
AggregationOperationContext context = rootContext;
555-
List<DBObject> operationDocuments = new ArrayList<DBObject>(operations.size());
556-
557-
for (AggregationOperation operation : operations) {
558-
559-
operationDocuments.add(operation.toDBObject(context));
560-
561-
if (operation instanceof FieldsExposingAggregationOperation) {
562-
563-
FieldsExposingAggregationOperation exposedFieldsOperation = (FieldsExposingAggregationOperation) operation;
564-
ExposedFields fields = exposedFieldsOperation.getFields();
565-
566-
if (operation instanceof InheritsFieldsAggregationOperation) {
567-
context = new InheritingExposedFieldsAggregationOperationContext(fields, context);
568-
} else {
569-
context = fields.exposesNoFields() ? DEFAULT_CONTEXT
570-
: new ExposedFieldsAggregationOperationContext(fields, context);
571-
}
572-
}
573-
}
574+
List<DBObject> operationDocuments = AggregationOperationRenderer.toDBObject(operations, rootContext);
574575

575576
DBObject command = new BasicDBObject("aggregate", inputCollectionName);
576577
command.put("pipeline", operationDocuments);
@@ -586,43 +587,7 @@ public DBObject toDbObject(String inputCollectionName, AggregationOperationConte
586587
*/
587588
@Override
588589
public String toString() {
589-
return SerializationUtils
590-
.serializeToJsonSafely(toDbObject("__collection__", new NoOpAggregationOperationContext()));
591-
}
592-
593-
/**
594-
* Simple {@link AggregationOperationContext} that just returns {@link FieldReference}s as is.
595-
*
596-
* @author Oliver Gierke
597-
*/
598-
private static class NoOpAggregationOperationContext implements AggregationOperationContext {
599-
600-
/*
601-
* (non-Javadoc)
602-
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
603-
*/
604-
@Override
605-
public DBObject getMappedObject(DBObject dbObject) {
606-
return dbObject;
607-
}
608-
609-
/*
610-
* (non-Javadoc)
611-
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(org.springframework.data.mongodb.core.aggregation.ExposedFields.AvailableField)
612-
*/
613-
@Override
614-
public FieldReference getReference(Field field) {
615-
return new DirectFieldReference(new ExposedField(field, true));
616-
}
617-
618-
/*
619-
* (non-Javadoc)
620-
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(java.lang.String)
621-
*/
622-
@Override
623-
public FieldReference getReference(String name) {
624-
return new DirectFieldReference(new ExposedField(new AggregationField(name), true));
625-
}
590+
return SerializationUtils.serializeToJsonSafely(toDbObject("__collection__", DEFAULT_CONTEXT));
626591
}
627592

628593
/**
@@ -662,7 +627,7 @@ public static boolean isReferingToSystemVariable(String fieldRef) {
662627
return false;
663628
}
664629

665-
/*
630+
/*
666631
* (non-Javadoc)
667632
* @see java.lang.Enum#toString()
668633
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.aggregation;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
22+
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
23+
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
24+
import org.springframework.data.mongodb.core.aggregation.Fields.AggregationField;
25+
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
26+
27+
import com.mongodb.DBObject;
28+
29+
/**
30+
* Rendering support for {@link AggregationOperation} into a {@link List} of {@link com.mongodb.DBObject}.
31+
*
32+
* @author Mark Paluch
33+
* @author Christoph Strobl
34+
* @since 1.10
35+
*/
36+
class AggregationOperationRenderer {
37+
38+
static final AggregationOperationContext DEFAULT_CONTEXT = new NoOpAggregationOperationContext();
39+
40+
/**
41+
* Render a {@link List} of {@link AggregationOperation} given {@link AggregationOperationContext} into their
42+
* {@link DBObject} representation.
43+
*
44+
* @param operations must not be {@literal null}.
45+
* @param context must not be {@literal null}.
46+
* @return the {@link List} of {@link DBObject}.
47+
*/
48+
static List<DBObject> toDBObject(List<AggregationOperation> operations, AggregationOperationContext rootContext) {
49+
50+
List<DBObject> operationDocuments = new ArrayList<DBObject>(operations.size());
51+
52+
AggregationOperationContext contextToUse = rootContext;
53+
54+
for (AggregationOperation operation : operations) {
55+
56+
operationDocuments.add(operation.toDBObject(contextToUse));
57+
58+
if (operation instanceof FieldsExposingAggregationOperation) {
59+
60+
FieldsExposingAggregationOperation exposedFieldsOperation = (FieldsExposingAggregationOperation) operation;
61+
ExposedFields fields = exposedFieldsOperation.getFields();
62+
63+
if (operation instanceof InheritsFieldsAggregationOperation) {
64+
contextToUse = new InheritingExposedFieldsAggregationOperationContext(fields, contextToUse);
65+
} else {
66+
contextToUse = fields.exposesNoFields() ? DEFAULT_CONTEXT
67+
: new ExposedFieldsAggregationOperationContext(exposedFieldsOperation.getFields(), contextToUse);
68+
}
69+
}
70+
}
71+
72+
return operationDocuments;
73+
}
74+
75+
/**
76+
* Simple {@link AggregationOperationContext} that just returns {@link FieldReference}s as is.
77+
*
78+
* @author Oliver Gierke
79+
*/
80+
private static class NoOpAggregationOperationContext implements AggregationOperationContext {
81+
82+
/*
83+
* (non-Javadoc)
84+
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
85+
*/
86+
@Override
87+
public DBObject getMappedObject(DBObject dbObject) {
88+
return dbObject;
89+
}
90+
91+
/*
92+
* (non-Javadoc)
93+
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(org.springframework.data.mongodb.core.aggregation.ExposedFields.AvailableField)
94+
*/
95+
@Override
96+
public FieldReference getReference(Field field) {
97+
return new DirectFieldReference(new ExposedField(field, true));
98+
}
99+
100+
/*
101+
* (non-Javadoc)
102+
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(java.lang.String)
103+
*/
104+
@Override
105+
public FieldReference getReference(String name) {
106+
return new DirectFieldReference(new ExposedField(new AggregationField(name), true));
107+
}
108+
}
109+
}

0 commit comments

Comments
 (0)