Skip to content

Commit 9d83331

Browse files
noterodrotbohm
authored andcommitted
DATAMONGO-652 - Added support for $elemMatch and $ positional operator.
1 parent 071cd16 commit 9d83331

File tree

2 files changed

+69
-6
lines changed
  • spring-data-mongodb/src
    • main/java/org/springframework/data/mongodb/core/query
    • test/java/org/springframework/data/mongodb/core/query

2 files changed

+69
-6
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2011 the original author or authors.
2+
* Copyright 2010-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,15 +17,25 @@
1717

1818
import java.util.HashMap;
1919
import java.util.Map;
20+
import java.util.Map.Entry;
21+
22+
import org.springframework.util.Assert;
2023

2124
import com.mongodb.BasicDBObject;
2225
import com.mongodb.DBObject;
2326

27+
/**
28+
* @author Thomas Risberg
29+
* @author Oliver Gierke
30+
* @author Patryk Wasik
31+
*/
2432
public class Field {
2533

26-
private Map<String, Integer> criteria = new HashMap<String, Integer>();
27-
28-
private Map<String, Object> slices = new HashMap<String, Object>();
34+
private final Map<String, Integer> criteria = new HashMap<String, Integer>();
35+
private final Map<String, Object> slices = new HashMap<String, Object>();
36+
private final Map<String, Criteria> elemMatchs = new HashMap<String, Criteria>();
37+
private String postionKey;
38+
private int positionValue;
2939

3040
public Field include(String key) {
3141
criteria.put(key, Integer.valueOf(1));
@@ -47,14 +57,50 @@ public Field slice(String key, int offset, int size) {
4757
return this;
4858
}
4959

60+
public Field elemMatch(String key, Criteria elemMatchCriteria) {
61+
elemMatchs.put(key, elemMatchCriteria);
62+
return this;
63+
}
64+
65+
/**
66+
* The array field must appear in the query. Only one positional {@code $} operator can appear in the projection and
67+
* only one array field can appear in the query.
68+
*
69+
* @param field query array field, must not be {@literal null} or empty.
70+
* @param value
71+
* @return
72+
*/
73+
public Field position(String field, int value) {
74+
75+
Assert.hasText(field, "Field must not be null or empty!");
76+
77+
postionKey = field;
78+
positionValue = value;
79+
80+
return this;
81+
}
82+
5083
public DBObject getFieldsObject() {
84+
5185
DBObject dbo = new BasicDBObject();
86+
5287
for (String k : criteria.keySet()) {
53-
dbo.put(k, (criteria.get(k)));
88+
dbo.put(k, criteria.get(k));
5489
}
90+
5591
for (String k : slices.keySet()) {
56-
dbo.put(k, new BasicDBObject("$slice", (slices.get(k))));
92+
dbo.put(k, new BasicDBObject("$slice", slices.get(k)));
5793
}
94+
95+
for (Entry<String, Criteria> entry : elemMatchs.entrySet()) {
96+
DBObject dbObject = new BasicDBObject("$elemMatch", entry.getValue().getCriteriaObject());
97+
dbo.put(entry.getKey(), dbObject);
98+
}
99+
100+
if (postionKey != null) {
101+
dbo.put(postionKey + ".$", positionValue);
102+
}
103+
58104
return dbo;
59105
}
60106
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.hamcrest.CoreMatchers.*;
1919
import static org.junit.Assert.*;
2020
import static org.springframework.data.mongodb.core.query.Criteria.*;
21+
import static org.springframework.data.mongodb.core.query.Query.*;
2122

2223
import org.junit.Assert;
2324
import org.junit.Rule;
@@ -32,6 +33,7 @@
3233
*
3334
* @author Thomas Risberg
3435
* @author Oliver Gierke
36+
* @author Patryk Wasik
3537
*/
3638
public class QueryTests {
3739

@@ -104,6 +106,21 @@ public void testQueryWithFieldsAndSlice() {
104106
Assert.assertEquals(expectedFields, q.getFieldsObject().toString());
105107
}
106108

109+
/**
110+
* @see DATAMONGO-652
111+
*/
112+
@Test
113+
public void testQueryWithFieldsElemMatchAndPositionalOperator() {
114+
115+
Query query = query(where("name").gte("M").lte("T").and("age").not().gt(22));
116+
query.fields().elemMatch("products", where("name").is("milk")).position("comments", 2);
117+
118+
String expected = "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}";
119+
assertThat(query.getQueryObject().toString(), is(expected));
120+
String expectedFields = "{ \"products\" : { \"$elemMatch\" : { \"name\" : \"milk\"}} , \"comments.$\" : 2}";
121+
assertThat(query.getFieldsObject().toString(), is(expectedFields));
122+
}
123+
107124
@Test
108125
public void testSimpleQueryWithChainedCriteria() {
109126
Query q = new Query(where("name").is("Thomas").and("age").lt(80));

0 commit comments

Comments
 (0)