DATAMONGO-586 - Yet another round of polish.

Added Apache license headers where missing. Removed separate package. Reduced visibility of ReferenceUtil as it's internal use only. Fixed formatting.
This commit is contained in:
Oliver Gierke
2013-04-26 19:42:30 +02:00
committed by Oliver Gierke
parent b7b61405f9
commit 6b634d08ce
8 changed files with 519 additions and 374 deletions

View File

@@ -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;

View File

@@ -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<T>(mappedResults, commandResult);
}
public <T> AggregationResults<T> aggregate(String inputCollectionName, Class<T> entityClass, AggregationOperation... operations) {
return aggregate(inputCollectionName, new AggregationPipeline(operations), entityClass);
}
public <T> AggregationResults<T> aggregate(String inputCollectionName, Class<T> entityClass,
AggregationOperation... operations) {
return aggregate(inputCollectionName, new AggregationPipeline(operations), entityClass);
}
protected String replaceWithResourceIfNecessary(String function) {

View File

@@ -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();
}

View File

@@ -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<DBObject> operations = new ArrayList<DBObject>();
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);
}
}
}

View File

@@ -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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/group/#stage._S_group">
* <code>$group</code>-operation
* </a>
*
* 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<String, DBObject> fields = new HashMap<String, DBObject>();
private static final String ID_KEY = "_id";
public GroupOperation(Object id) {
this.id = id;
}
private final Object id;
private final Map<String, DBObject> fields = new HashMap<String, DBObject>();
public DBObject getDBObject() {
DBObject projection = new BasicDBObject(ID_KEY, id);
for (Entry<String, DBObject> 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<String, DBObject> entry : fields.entrySet()) {
projection.put(entry.getKey(), entry.getValue());
}
return this;
}
return new BasicDBObject("$group", projection);
}
/**
* Adds a field with the
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_addToSet">$addToSet operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$addToSet: "$field"}
* }}
* </pre>
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_first">$first operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$first: "$field"}
* }}
* </pre>
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_last">$last operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$last: "$field"}
* }}
* </pre>
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_max">$max operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$max: "$field"}
* }}
* </pre>
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_min">$min operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$min: "$field"}
* }}
* </pre>
* @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 <a
* href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_addToSet">$addToSet operation</a>.
*
* <pre>
* { $group : {
* _id : "$id_field",
* name : { $addToSet : "$field" }
* }}
* </pre>
*
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_avg">$avg operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$avg: "$field"}
* }}
* </pre>
* @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.
*
* <pre>
* { $group : {
* _id : "$id_field",
* name : { $first : "$field" }
* }}
* </pre>
*
* @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 <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_last">$last
* operation</a>.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$last: "$field"}
* }}
* </pre>
*
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_push">$push operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$push: "$field"}
* }}
* </pre>
* @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 <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_max">$max
* operation</a>.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$max: "$field"}
* }}
* </pre>
*
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_sum">$sum operation</a>
* with a constant value.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$sum: increment}
* }}
* </pre>
* @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 <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_min">$min
* operation</a>.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$min: "$field"}
* }}
* </pre>
*
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_sum">$sum operation</a>
* count every item.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$sum: 1}
* }}
* </pre>
* @param name key of the field
* @return
*
*/
public GroupOperation count(String name) {
return count(name, 1);
}
/**
* Adds a field with the <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_avg">$avg
* operation</a>.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$avg: "$field"}
* }}
* </pre>
*
* @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
* <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_sum">$sum operation</a>.
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$sum: "$field"}
* }}
* </pre>
* @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 <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_push">$push
* operation</a>.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$push: "$field"}
* }}
* </pre>
*
* @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 <code>$group</code> operation with <code>_id</code> referencing to a field of the document. The
* returned db object equals to <pre>{_id: "$field"}</pre>
* @param field
* @return
*/
public static GroupOperation group(String field) {
return new GroupOperation(ReferenceUtil.safeReference(field));
}
/**
* Adds a field with the <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_sum">$sum
* operation</a> with a constant value.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$sum: increment}
* }}
* </pre>
*
* @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 <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_sum">$sum
* operation</a> count every item.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$sum: 1}
* }}
* </pre>
*
* @param name key of the field
* @return
*/
public GroupOperation count(String name) {
return count(name, 1);
}
/**
* Creates a <code>$group</code> 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:
* <pre>
*
* group(idField("path"), idField("pageView", "page.views"), idField("field3"))
*
* </pre>
* which would result in:
* <pre>
*
* {$group: {_id: {path: "$path", pageView: "$page.views", field3: "$field3"}}}
*
* </pre>
* @param idFields
* @return
*/
public static GroupOperation group(IdField... idFields) {
Assert.notNull(idFields, "Combined id is null");
/**
* Adds a field with the <a href="http://docs.mongodb.org/manual/reference/aggregation/addToSet/#grp._S_sum">$sum
* operation</a>.
*
* <pre>
* {$group: {
* _id: "$id_field",
* name: {$sum: "$field"}
* }}
* </pre>
*
* @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 <code>$group</code> operation with <code>_id</code> referencing to a field of the document. The returned
* db object equals to
*
* <pre>
* {_id: "$field"}
* </pre>
*
* @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 <code>$group</code> operation.
*
* For example:
* <pre>
* {$group: {_id: {key: "$value"}}}
* </pre>
*/
public static class IdField {
/**
* Creates a <code>$group</code> 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:
*
* <pre>
*
* group(idField(&quot;path&quot;), idField(&quot;pageView&quot;, &quot;page.views&quot;), idField(&quot;field3&quot;))
*
* </pre>
*
* which would result in:
*
* <pre>
*
* {$group: {_id: {path: "$path", pageView: "$page.views", field3: "$field3"}}}
*
* </pre>
*
* @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 <code>$group</code> operation. For example:
*
* <pre>
* {$group: {_id: {key: "$value"}}}
* </pre>
*/
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:
* <pre>
* _id: {field: "$field"}
* </pre>
* @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
* <pre>
* _id: {key: "$field"}
* </pre>
* @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:
*
* <pre>
* _id : { field : "$field" }
* </pre>
*
* @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.
*
* <pre>
* _id: {key: "$field"}
* </pre>
*
* @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);
}
}
}

View File

@@ -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 <code>$match</code>-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);
}
}

View File

@@ -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 <code>$</code>
*
* @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;
}
}

View File

@@ -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<TagCount> results = mongoTemplate.aggregate(INPUT_COLLECTION, pipeline, TagCount.class);
assertThat(results, is(notNullValue()));
assertThat(results.getServerUsed(), is("/127.0.0.1:27017"));
List<TagCount> 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<TagCount> results = mongoTemplate.aggregate(INPUT_COLLECTION, pipeline, TagCount.class);
assertThat(results, is(notNullValue()));
assertThat(results.getServerUsed(), is("/127.0.0.1:27017"));
List<TagCount> 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<TagCount> results = mongoTemplate.aggregate(INPUT_COLLECTION, pipeline, TagCount.class);
assertThat(results, is(notNullValue()));
assertThat(results.getServerUsed(), is("/127.0.0.1:27017"));
List<TagCount> 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"));