diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index ad0f74ad1..2e85ecc5a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -19,6 +19,9 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.AggregationPipeline; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.geo.GeoResult; import org.springframework.data.mongodb.core.geo.GeoResults; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 45cf3ff80..c9a9136d4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -53,7 +53,7 @@ import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.BeanWrapper; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.aggregation.operation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.aggregation.AggregationPipeline; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -118,6 +118,7 @@ import com.mongodb.util.JSONParseException; * @author Amol Nayak * @author Patryk Wasik * @author Tobias Trelle + * @author Sebastian Herold */ public class MongoTemplate implements MongoOperations, ApplicationContextAware { @@ -1239,10 +1240,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return new AggregationResults(mappedResults, commandResult); } - public AggregationResults aggregate(String inputCollectionName, Class entityClass, AggregationOperation... operations) { - return aggregate(inputCollectionName, new AggregationPipeline(operations), entityClass); - } - + public AggregationResults aggregate(String inputCollectionName, Class entityClass, + AggregationOperation... operations) { + return aggregate(inputCollectionName, new AggregationPipeline(operations), entityClass); + } protected String replaceWithResourceIfNecessary(String function) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java index bff5cd6f8..e1a5bcf97 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java @@ -1,19 +1,34 @@ -package org.springframework.data.mongodb.core.aggregation.operation; +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.aggregation; import com.mongodb.DBObject; /** - * Represents one single operation in an aggregation pipeline - * + * Represents one single operation in an aggregation pipeline. + * * @author Sebastian Herold * @since 1.3 */ public interface AggregationOperation { - /** - * Gets the {@link DBObject} behind this operation - * - * @return the DBObject - */ - DBObject getDBObject(); + /** + * Gets the {@link DBObject} backing this operation + * + * @return the DBObject + */ + DBObject getDBObject(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java index 492096792..f1cb75551 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; import org.springframework.data.domain.Sort; -import org.springframework.data.mongodb.core.aggregation.operation.AggregationOperation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.util.Assert; @@ -40,17 +39,24 @@ public class AggregationPipeline { private final List operations = new ArrayList(); - public AggregationPipeline() { - } + public AggregationPipeline() { + } - public AggregationPipeline(AggregationOperation... operations) { - Assert.notNull(operations, "Operations are missing"); + /** + * Creates a new {@link AggregationPipeline} from the given {@link AggregationOperation}s. + * + * @param operations must not be {@literal null} or empty. + */ + public AggregationPipeline(AggregationOperation... operations) { - for (AggregationOperation operation : operations) { - Assert.notNull(operation, "Operation is not allowed to be null"); - this.operations.add(operation.getDBObject()); - } - } + Assert.notNull(operations, "Operations must not be null!"); + Assert.isTrue(operations.length > 0, "operations must not be empty!"); + + for (AggregationOperation operation : operations) { + Assert.notNull(operation, "Operation is not allowed to be null"); + this.operations.add(operation.getDBObject()); + } + } /** * Adds a projection operation to the pipeline. @@ -174,17 +180,18 @@ public class AggregationPipeline { return operations; } - /** - * creates an empty pipeline - * @return the new pipeline - */ - public static AggregationPipeline pipeline() { - return new AggregationPipeline(); - } + /** + * creates an empty pipeline + * + * @return the new pipeline + */ + public static AggregationPipeline pipeline() { + return new AggregationPipeline(); + } private AggregationPipeline addDocumentOperation(String opName, String operation) { - Assert.hasText(operation, "Missing operation name!"); + Assert.hasText(operation, "Operation must not be null or empty!"); return addOperation(opName, parseJson(operation)); } @@ -194,10 +201,11 @@ public class AggregationPipeline { } private DBObject parseJson(String json) { + try { return (DBObject) JSON.parse(json); } catch (JSONParseException e) { - throw new IllegalArgumentException("Not a valid JSON document: " + json, e); + throw new IllegalArgumentException("Invalid JSON document: " + json, e); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index 739594a2f..e5746882e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -1,334 +1,381 @@ -package org.springframework.data.mongodb.core.aggregation.operation; - -import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; -import org.springframework.data.mongodb.core.aggregation.ReferenceUtil; -import org.springframework.util.Assert; +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.aggregation; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import org.springframework.util.Assert; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; + /** - * Encapsulates the aggregation framework - * - * $group-operation - * - * + * Encapsulates the aggregation framework {@code $group}-operation. + * + * @see http://docs.mongodb.org/manual/reference/aggregation/group/#stage._S_group * @author Sebastian Herold * @since 1.3 */ public class GroupOperation implements AggregationOperation { - private static final String ID_KEY = "_id"; - private final Object id; - private final Map fields = new HashMap(); + private static final String ID_KEY = "_id"; - public GroupOperation(Object id) { - this.id = id; - } + private final Object id; + private final Map fields = new HashMap(); - public DBObject getDBObject() { - DBObject projection = new BasicDBObject(ID_KEY, id); - for (Entry entry : fields.entrySet()) { - projection.put(entry.getKey(), entry.getValue()); - } - return new BasicDBObject("$group", projection); - } + public GroupOperation(Object id) { + this.id = id; + } - public GroupOperation addField(String key, DBObject value) { - Assert.hasText(key, "Key is empty"); - Assert.notNull(value, "Value is null"); + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getDBObject() + */ + public DBObject getDBObject() { - String trimmedKey = key.trim(); - if (ID_KEY.equals(trimmedKey)) { - throw new IllegalArgumentException("_id field can only be set in constructor"); - } + DBObject projection = new BasicDBObject(ID_KEY, id); - fields.put(key, value); + for (Entry entry : fields.entrySet()) { + projection.put(entry.getKey(), entry.getValue()); + } - return this; - } + return new BasicDBObject("$group", projection); + } - /** - * Adds a field with the - * $addToSet operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$addToSet: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation addToSet(String name, String field) { - return addOperation("$addToSet", name, field); - } + public GroupOperation addField(String key, DBObject value) { - /** - * Adds a field with the - * $first operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$first: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation first(String name, String field) { - return addOperation("$first", name, field); - } + Assert.hasText(key, "Key is empty"); + Assert.notNull(value, "Value is null"); - /** - * Adds a field with the - * $last operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$last: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation last(String name, String field) { - return addOperation("$last", name, field); - } + String trimmedKey = key.trim(); - /** - * Adds a field with the - * $max operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$max: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation max(String name, String field) { - return addOperation("$max", name, field); - } + if (ID_KEY.equals(trimmedKey)) { + throw new IllegalArgumentException("_id field can only be set in constructor"); + } - /** - * Adds a field with the - * $min operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$min: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation min(String name, String field) { - return addOperation("$min", name, field); - } + fields.put(key, value); + return this; + } + /** + * Adds a field with the $addToSet operation. + * + *
+	 * { $group : {
+	 *      _id : "$id_field",
+	 *     name : { $addToSet : "$field" }
+	 * }}
+	 * 
+ * + * @see http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_addToSet + * @param name key of the field. + * @param field reference to a field of the document. + * @return + */ + public GroupOperation addToSet(String name, String field) { + return addOperation("$addToSet", name, field); + } - /** - * Adds a field with the - * $avg operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$avg: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation avg(String name, String field) { - return addOperation("$avg", name, field); - } + /** + * Adds a field with the {@code $first} operation. + * + *
+	 * { $group : {
+	 *      _id : "$id_field",
+	 *     name : { $first : "$field" }
+	 * }}
+	 * 
+ * + * @see http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_first + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation first(String name, String field) { + return addOperation("$first", name, field); + } + /** + * Adds a field with the $last + * operation. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$last: "$field"}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation last(String name, String field) { + return addOperation("$last", name, field); + } - /** - * Adds a field with the - * $push operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$push: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation push(String name, String field) { - return addOperation("$push", name, field); - } + /** + * Adds a field with the $max + * operation. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$max: "$field"}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation max(String name, String field) { + return addOperation("$max", name, field); + } - /** - * Adds a field with the - * $sum operation - * with a constant value. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$sum: increment}
-     *     }}
-     * 
- * @param name key of the field - * @param increment increment for each item - * @return - * - */ - public GroupOperation count(String name, double increment) { - return addField(name, new BasicDBObject("$sum", increment)); - } + /** + * Adds a field with the $min + * operation. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$min: "$field"}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation min(String name, String field) { + return addOperation("$min", name, field); + } - /** - * Adds a field with the - * $sum operation - * count every item. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$sum: 1}
-     *     }}
-     * 
- * @param name key of the field - * @return - * - */ - public GroupOperation count(String name) { - return count(name, 1); - } + /** + * Adds a field with the $avg + * operation. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$avg: "$field"}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation avg(String name, String field) { + return addOperation("$avg", name, field); + } - /** - * Adds a field with the - * $sum operation. - *
-     *     {$group: {
-     *          _id: "$id_field",
-     *          name: {$sum: "$field"}
-     *     }}
-     * 
- * @param name key of the field - * @param field reference to a field of the document - * @return - * - */ - public GroupOperation sum(String name, String field) { - return addOperation("$sum", name, field); - } + /** + * Adds a field with the $push + * operation. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$push: "$field"}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation push(String name, String field) { + return addOperation("$push", name, field); + } - /** - * Creates a $group operation with _id referencing to a field of the document. The - * returned db object equals to
{_id: "$field"}
- * @param field - * @return - */ - public static GroupOperation group(String field) { - return new GroupOperation(ReferenceUtil.safeReference(field)); - } + /** + * Adds a field with the $sum + * operation with a constant value. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$sum: increment}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param increment increment for each item + * @return + */ + public GroupOperation count(String name, double increment) { + return addField(name, new BasicDBObject("$sum", increment)); + } - protected GroupOperation addOperation(String operation, String name, String field) { - return addField(name, new BasicDBObject(operation, ReferenceUtil.safeReference(field))); - } + /** + * Adds a field with the $sum + * operation count every item. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$sum: 1}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @return + */ + public GroupOperation count(String name) { + return count(name, 1); + } - /** - * Creates a $group operation with a id that consists of multiple fields. - * - * Using {@link IdField#idField(String)} or {@link IdField#idField(String, String)} you can easily create - * complex id fields like: - *
-     *
-     *     group(idField("path"), idField("pageView", "page.views"), idField("field3"))
-     *
-     * 
- * which would result in: - *
-     *
-     *     {$group: {_id: {path: "$path", pageView: "$page.views", field3: "$field3"}}}
-     *
-     * 
- * @param idFields - * @return - */ - public static GroupOperation group(IdField... idFields) { - Assert.notNull(idFields, "Combined id is null"); + /** + * Adds a field with the $sum + * operation. + * + *
+	 *     {$group: {
+	 *          _id: "$id_field",
+	 *          name: {$sum: "$field"}
+	 *     }}
+	 * 
+ * + * @param name key of the field + * @param field reference to a field of the document + * @return + */ + public GroupOperation sum(String name, String field) { + return addOperation("$sum", name, field); + } - BasicDBObject id = new BasicDBObject(); - for (IdField idField : idFields) { - id.put(idField.getKey(), idField.getValue()); - } + /** + * Creates a $group operation with _id referencing to a field of the document. The returned + * db object equals to + * + *
+	 * {_id: "$field"}
+	 * 
+ * + * @param field + * @return + */ + public static GroupOperation group(String field) { + return new GroupOperation(ReferenceUtil.safeReference(field)); + } - return new GroupOperation(id); - } + protected GroupOperation addOperation(String operation, String name, String field) { + return addField(name, new BasicDBObject(operation, ReferenceUtil.safeReference(field))); + } - /** - * Represents a single field in a complex id of a $group operation. - * - * For example: - *
-     *     {$group: {_id: {key: "$value"}}}
-     * 
- */ - public static class IdField { + /** + * Creates a $group operation with a id that consists of multiple fields. Using + * {@link IdField#idField(String)} or {@link IdField#idField(String, String)} you can easily create complex id fields + * like: + * + *
+	 * 
+	 * group(idField("path"), idField("pageView", "page.views"), idField("field3"))
+	 * 
+	 * 
+ * + * which would result in: + * + *
+	 * 
+	 *     {$group: {_id: {path: "$path", pageView: "$page.views", field3: "$field3"}}}
+	 * 
+	 * 
+ * + * @param idFields + * @return + */ + public static GroupOperation group(IdField... idFields) { + Assert.notNull(idFields, "Combined id is null"); - private final String key; - private final String value; + BasicDBObject id = new BasicDBObject(); + for (IdField idField : idFields) { + id.put(idField.getKey(), idField.getValue()); + } - public IdField(String key, String value) { - Assert.hasText(key, "Key is empty"); - Assert.hasText(value, "Value is empty"); + return new GroupOperation(id); + } - this.key = ReferenceUtil.safeNonReference(key); - this.value = ReferenceUtil.safeReference(value); - } + /** + * Represents a single field in a complex id of a $group operation. For example: + * + *
+	 *     {$group: {_id: {key: "$value"}}}
+	 * 
+ */ + public static class IdField { - public String getKey() { - return key; - } + private final String key; + private final String value; - public String getValue() { - return value; - } + /** + * Creates a new {@link IdField} with the given key and value. + * + * @param key must not be {@literal null} or empty. + * @param value must not be {@literal null} or empty. + */ + public IdField(String key, String value) { - /** - * Creates an id field with the name of the referenced field: - *
-         *     _id: {field: "$field"}
-         * 
- * @param field reference to a field of the document - * @return the id field - */ - public static IdField idField(String field) { - return new IdField(field, field); - } + Assert.hasText(key, "Key must not be null or empty"); + Assert.hasText(value, "Value must not be null or empty"); - /** - * Creates an id field with key and reference - *
-         *     _id: {key: "$field"}
-         * 
- * @param key the key - * @param field reference to a field of the document - * @return the id field - */ - public static IdField idField(String key, String field) { - return new IdField(key, field); - } - } + this.key = ReferenceUtil.safeNonReference(key); + this.value = ReferenceUtil.safeReference(value); + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + /** + * Creates an id field with the name of the referenced field: + * + *
+		 * _id : { field : "$field" }
+		 * 
+ * + * @param field reference to a field of the document + * @return the id field + */ + public static IdField idField(String field) { + return new IdField(field, field); + } + + /** + * Creates an id field with key and reference. + * + *
+		 * _id: {key: "$field"}
+		 * 
+ * + * @param key the key + * @param field reference to a field of the document + * @return the id field + */ + public static IdField idField(String key, String field) { + return new IdField(key, field); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index 1c4bb0f1d..7851ac532 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -1,28 +1,63 @@ -package org.springframework.data.mongodb.core.aggregation.operation; +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.aggregation; + +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.util.Assert; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -import org.springframework.data.mongodb.core.query.Criteria; /** - * Encapsulates the $match-operation - * + * Encapsulates the {@code $match}-operation + * * @author Sebastian Herold * @since 1.3 */ public class MatchOperation implements AggregationOperation { - private final DBObject criteria; + private final DBObject criteria; - public MatchOperation(Criteria criteria) { - this.criteria = criteria.getCriteriaObject(); - } + /** + * Creates a new {@link MatchOperation} for the given {@link Criteria}. + * + * @param criteria must not be {@literal null}. + */ + public MatchOperation(Criteria criteria) { - public DBObject getDBObject() { - return new BasicDBObject("$match", criteria); - } + Assert.notNull(criteria, "Criteria must not be null!"); + this.criteria = criteria.getCriteriaObject(); + } + + /** + * Factory method to create a new {@link MatchOperation} for the given {@link Criteria}. + * + * @param criteria must not be {@literal null}. + * @return + */ + public static MatchOperation match(Criteria criteria) { + return new MatchOperation(criteria); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getDBObject() + */ + public DBObject getDBObject() { + return new BasicDBObject("$match", criteria); + } - public static MatchOperation match(Criteria criteria) { - return new MatchOperation(criteria); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReferenceUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReferenceUtil.java index ac65b5379..7b6c23ca1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReferenceUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReferenceUtil.java @@ -1,45 +1,63 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.data.mongodb.core.aggregation; import org.springframework.util.Assert; /** * Utility class for mongo db reference operator $ + * + * @author Sebastian Herold + * @since 1.3 */ -public class ReferenceUtil { +class ReferenceUtil { - public static final String REFERENCE_PREFIX = "$"; + private static final String REFERENCE_PREFIX = "$"; - /** - * Ensures that the returned string begins with {@link #REFERENCE_PREFIX $} - * - * @param key reference key with or without {@link #REFERENCE_PREFIX $} at the beginning - * @return key that definitely begins with {@link #REFERENCE_PREFIX $} - */ - public static String safeReference(String key) { + /** + * Ensures that the returned string begins with {@link #REFERENCE_PREFIX}. + * + * @param key reference key with or without {@link #REFERENCE_PREFIX} at the beginning. + * @return key that definitely begins with {@link #REFERENCE_PREFIX}. + */ + public static String safeReference(String key) { - Assert.hasText(key); + Assert.hasText(key); - if (!key.startsWith(REFERENCE_PREFIX)) { - return REFERENCE_PREFIX + key; - } else { - return key; - } - } + if (!key.startsWith(REFERENCE_PREFIX)) { + return REFERENCE_PREFIX + key; + } else { + return key; + } + } - /** - * Ensures that the returned string does not start with {@link #REFERENCE_PREFIX $} - * - * @param field reference key with or without {@link #REFERENCE_PREFIX $} at the beginning - * @return key that definitely does not begin with {@link #REFERENCE_PREFIX $} - */ - public static String safeNonReference(String field) { + /** + * Ensures that the returned string does not start with {@link #REFERENCE_PREFIX}. + * + * @param field reference key with or without {@link #REFERENCE_PREFIX} at the beginning. + * @return key that definitely does not begin with {@link #REFERENCE_PREFIX}. + */ + public static String safeNonReference(String field) { - Assert.hasText(field); + Assert.hasText(field); - if (field.startsWith(REFERENCE_PREFIX)) { - return field.substring(REFERENCE_PREFIX.length()); - } + if (field.startsWith(REFERENCE_PREFIX)) { + return field.substring(REFERENCE_PREFIX.length()); + } - return field; - } + return field; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index b08f6e05f..d56990793 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -89,17 +89,23 @@ public class AggregationTests { createDocuments(); - AggregationPipeline pipeline = new AggregationPipeline().project("{_id:0,tags:1}}").unwind("tags") - .group("{_id:\"$tags\", n:{$sum:1}}").project("{tag: \"$_id\", n:1, _id:0}") - .sort(new Sort(new Sort.Order(Direction.DESC, "n"))); + AggregationPipeline pipeline = new AggregationPipeline(). // + project("{_id:0,tags:1}}"). // + unwind("tags"). // + group("{_id:\"$tags\", n:{$sum:1}}"). // + project("{tag: \"$_id\", n:1, _id:0}"). // + sort(new Sort(new Sort.Order(Direction.DESC, "n"))); AggregationResults results = mongoTemplate.aggregate(INPUT_COLLECTION, pipeline, TagCount.class); + assertThat(results, is(notNullValue())); assertThat(results.getServerUsed(), is("/127.0.0.1:27017")); List tagCount = results.getAggregationResult(); + assertThat(tagCount, is(notNullValue())); assertThat(tagCount.size(), is(3)); + assertTagCount("spring", 3, tagCount.get(0)); assertTagCount("mongodb", 2, tagCount.get(1)); assertTagCount("nosql", 1, tagCount.get(2)); @@ -116,14 +122,20 @@ public class AggregationTests { @Test public void shouldAggregateEmptyCollection() { - AggregationPipeline pipeline = new AggregationPipeline().project("{_id:0,tags:1}}").unwind("$tags") - .group("{_id:\"$tags\", n:{$sum:1}}").project("{tag: \"$_id\", n:1, _id:0}").sort("{n:-1}"); + AggregationPipeline pipeline = new AggregationPipeline(). // + project("{_id:0,tags:1}}"). // + unwind("$tags").// + group("{_id:\"$tags\", n:{$sum:1}}").// + project("{tag: \"$_id\", n:1, _id:0}").// + sort("{n:-1}"); AggregationResults results = mongoTemplate.aggregate(INPUT_COLLECTION, pipeline, TagCount.class); + assertThat(results, is(notNullValue())); assertThat(results.getServerUsed(), is("/127.0.0.1:27017")); List tagCount = results.getAggregationResult(); + assertThat(tagCount, is(notNullValue())); assertThat(tagCount.size(), is(0)); } @@ -132,14 +144,19 @@ public class AggregationTests { public void shouldDetectResultMismatch() { createDocuments(); - AggregationPipeline pipeline = new AggregationPipeline().project("{_id:0,tags:1}}").unwind("$tags") - .group("{_id:\"$tags\", count:{$sum:1}}").limit(2); + AggregationPipeline pipeline = new AggregationPipeline(). // + project("{_id:0,tags:1}}"). // + unwind("$tags"). // + group("{_id:\"$tags\", count:{$sum:1}}"). // + limit(2); AggregationResults results = mongoTemplate.aggregate(INPUT_COLLECTION, pipeline, TagCount.class); + assertThat(results, is(notNullValue())); assertThat(results.getServerUsed(), is("/127.0.0.1:27017")); List tagCount = results.getAggregationResult(); + assertThat(tagCount, is(notNullValue())); assertThat(tagCount.size(), is(2)); assertTagCount(null, 0, tagCount.get(0)); @@ -153,6 +170,7 @@ public class AggregationTests { private void createDocuments() { DBCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); + coll.insert(createDocument("Doc1", "spring", "mongodb", "nosql")); coll.insert(createDocument("Doc2", "spring", "mongodb")); coll.insert(createDocument("Doc3", "spring"));