DATAMONGO-1761 - Add distinct operation to MongoTemplate.

We now support distinct queries via MongoTemplate to select distinct field values based on a collection and query.

List<String> distinctNames = template.findDistinct("name", Person.class, String.class);

List<String> distinctNames = template.query(Person.class).distinct("name").as(String.class).all();

Original pull request: #494.
Related pull request: #514.
This commit is contained in:
eric
2017-07-28 21:17:04 +08:00
committed by Mark Paluch
parent 7401e5e01b
commit c9f3a52dc0
2 changed files with 60 additions and 4 deletions

View File

@@ -117,15 +117,12 @@ import org.springframework.util.ObjectUtils;
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.DistinctIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MapReduceIterable;
import com.mongodb.client.MongoCollection;
@@ -164,6 +161,7 @@ import com.mongodb.util.JSONParseException;
* @author Laszlo Csontos
* @author Maninder Singh
* @author Borislav Rangelov
* @author duozhilin
*/
@SuppressWarnings("deprecation")
public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider {
@@ -799,6 +797,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return doFindOne(collectionName, new Document(idKey, id), new Document(), entityClass);
}
public <T, Z> List<T> distinct(String field, Class<Z> entityClass, Class<T> resultClass) {
return distinct(new Query(), field, determineCollectionName(entityClass), resultClass);
}
public <T, Z> List<T> distinct(Query query, String field, Class<Z> entityClass, Class<T> resultClass) {
return distinct(query, field, determineCollectionName(entityClass), resultClass);
}
public <T> List<T> distinct(Query query, String field, String collectionName, Class<T> resultClass) {
MongoCollection<Document> collection = this.getCollection(collectionName);
DistinctIterable<T> iterable = collection.distinct(field, query.getQueryObject(), resultClass);
MongoCursor<T> cursor = iterable.iterator();
List<T> result = new ArrayList<T>();
while (cursor.hasNext()) {
T object = cursor.next();
result.add(object);
}
return result;
}
@Override
public <T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass) {
return geoNear(near, entityClass, determineCollectionName(entityClass));

View File

@@ -113,6 +113,7 @@ import com.mongodb.client.result.UpdateResult;
* @author Christoph Strobl
* @author Mark Paluch
* @author Laszlo Csontos
* @author duozhilin
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
@@ -726,6 +727,39 @@ public class MongoTemplateTests {
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<String> 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 {