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 30cec4d918..4f2bb528d0 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 @@ -15,6 +15,33 @@ */ package org.springframework.data.mongodb.core; +import com.mongodb.Cursor; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import com.mongodb.Mongo; +import com.mongodb.MongoClient; +import com.mongodb.MongoException; +import com.mongodb.ReadPreference; +import com.mongodb.WriteConcern; +import com.mongodb.client.AggregateIterable; +import com.mongodb.client.DistinctIterable; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MapReduceIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.CountOptions; +import com.mongodb.client.model.CreateCollectionOptions; +import com.mongodb.client.model.DeleteOptions; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.FindOneAndDeleteOptions; +import com.mongodb.client.model.FindOneAndUpdateOptions; +import com.mongodb.client.model.ReturnDocument; +import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.result.DeleteResult; +import com.mongodb.client.result.UpdateResult; +import com.mongodb.util.JSONParseException; + import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.SerializationUtils.*; @@ -127,31 +154,29 @@ import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; -import com.mongodb.Cursor; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.Mongo; -import com.mongodb.MongoClient; -import com.mongodb.MongoException; -import com.mongodb.ReadPreference; -import com.mongodb.WriteConcern; -import com.mongodb.client.AggregateIterable; -import com.mongodb.client.FindIterable; -import com.mongodb.client.MapReduceIterable; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoCursor; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.CountOptions; -import com.mongodb.client.model.CreateCollectionOptions; -import com.mongodb.client.model.DeleteOptions; -import com.mongodb.client.model.Filters; -import com.mongodb.client.model.FindOneAndDeleteOptions; -import com.mongodb.client.model.FindOneAndUpdateOptions; -import com.mongodb.client.model.ReturnDocument; -import com.mongodb.client.model.UpdateOptions; -import com.mongodb.client.result.DeleteResult; -import com.mongodb.client.result.UpdateResult; -import com.mongodb.util.JSONParseException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Scanner; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.SerializationUtils.serializeToJsonSafely; /** * Primary implementation of {@link MongoOperations}. @@ -173,6 +198,7 @@ * @author Laszlo Csontos * @author Maninder Singh * @author Borislav Rangelov + * @author duozhilin */ @SuppressWarnings("deprecation") public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider { @@ -808,6 +834,30 @@ public T findById(Object id, Class entityClass, String collectionName) { return doFindOne(collectionName, new Document(idKey, id), new Document(), entityClass); } + public List distinct(String field, Class entityClass, Class resultClass) { + return distinct(new Query(), field, determineCollectionName(entityClass), resultClass); + } + + public List distinct(Query query, String field, Class entityClass, Class resultClass) { + return distinct(query, field, determineCollectionName(entityClass), resultClass); + } + + public List distinct(Query query, String field, String collectionName, Class resultClass) { + MongoCollection collection = this.getCollection(collectionName); + DistinctIterable iterable = collection.distinct(field, query.getQueryObject(), resultClass); + + MongoCursor cursor = iterable.iterator(); + + List result = new ArrayList(); + + while (cursor.hasNext()) { + T object = cursor.next(); + result.add(object); + } + + return result; + } + @Override public GeoResults geoNear(NearQuery near, Class entityClass) { return geoNear(near, entityClass, determineCollectionName(entityClass)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index d0baae3544..ed211b8b8f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -15,6 +15,17 @@ */ package org.springframework.data.mongodb.core; +import com.mongodb.DBRef; +import com.mongodb.Mongo; +import com.mongodb.MongoException; +import com.mongodb.ReadPreference; +import com.mongodb.WriteConcern; +import com.mongodb.client.FindIterable; +import com.mongodb.client.ListIndexesIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.result.UpdateResult; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.hamcrest.Matchers.*; @@ -99,16 +110,50 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import com.mongodb.DBRef; -import com.mongodb.Mongo; -import com.mongodb.MongoException; -import com.mongodb.ReadPreference; -import com.mongodb.WriteConcern; -import com.mongodb.client.FindIterable; -import com.mongodb.client.ListIndexesIterable; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoCursor; -import com.mongodb.client.result.UpdateResult; +import java.lang.reflect.InvocationTargetException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isOneOf; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeThat; +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; +import static org.springframework.data.mongodb.core.query.Update.update; /** * Integration test for {@link MongoTemplate}. @@ -122,6 +167,7 @@ * @author Christoph Strobl * @author Mark Paluch * @author Laszlo Csontos + * @author duozhilin */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:infrastructure.xml") @@ -749,6 +795,39 @@ public void testFindAndRemove() throws Exception { assertThat(notFound, nullValue()); } + @Test + public void testDistinct() { + Address address1 = new Address(); + address1.state = "PA"; + address1.city = "Philadelphia"; + + Address address2 = new Address(); + address2.state = "PA"; + address2.city = " New York"; + + MyPerson person1 = new MyPerson(); + person1.name = "Ben"; + person1.address = address1; + + MyPerson person2 = new MyPerson(); + person2.name = "Eric"; + person2.address = address2; + + template.save(person1); + template.save(person2); + + List nameList = template.distinct("name", MyPerson.class, String.class); + assertTrue(nameList.containsAll(Arrays.asList(person1.getName(), person2.getName()))); + + Query query = new BasicQuery("{'address.state' : 'PA'}"); + nameList = template.distinct(query, "name", MyPerson.class, String.class); + assertTrue(nameList.containsAll(Arrays.asList(person1.getName(), person2.getName()))); + + String collectionName = template.determineCollectionName(MyPerson.class); + nameList = template.distinct(query, "name", collectionName, String.class); + assertTrue(nameList.containsAll(Arrays.asList(person1.getName(), person2.getName()))); + } + @Test public void testUsingAnInQueryWithObjectId() throws Exception {