Skip to content

Commit 05bf67b

Browse files
authored
Test expressions in context (#1057)
JAVA-4820
1 parent d96bfd5 commit 05bf67b

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed

driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ public static ArrayExpression<StringExpression> ofStringArray(final String... ar
172172
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(result)));
173173
}
174174

175+
public static DocumentExpression current() {
176+
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT")))
177+
.assertImplementsAllExpressions();
178+
}
179+
180+
public static <R extends Expression> MapExpression<R> currentAsMap() {
181+
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT")))
182+
.assertImplementsAllExpressions();
183+
}
184+
175185
@SafeVarargs // nothing is stored in the array
176186
public static <T extends Expression> ArrayExpression<T> ofArray(final T... array) {
177187
Assertions.notNull("array", array);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.client.model.expressions;
18+
19+
import com.mongodb.MongoClientSettings;
20+
import com.mongodb.client.AggregateIterable;
21+
import com.mongodb.client.FindIterable;
22+
import com.mongodb.client.MongoClient;
23+
import com.mongodb.client.MongoClients;
24+
import com.mongodb.client.MongoCollection;
25+
import com.mongodb.client.model.Aggregates;
26+
import org.bson.Document;
27+
import org.bson.conversions.Bson;
28+
import org.junit.jupiter.api.AfterEach;
29+
import org.junit.jupiter.api.BeforeEach;
30+
import org.junit.jupiter.api.Test;
31+
32+
import java.util.ArrayList;
33+
import java.util.Arrays;
34+
import java.util.List;
35+
36+
import static com.mongodb.client.model.Accumulators.sum;
37+
import static com.mongodb.client.model.Aggregates.match;
38+
import static com.mongodb.client.model.Aggregates.project;
39+
import static com.mongodb.client.model.Filters.expr;
40+
import static com.mongodb.client.model.Projections.computed;
41+
import static com.mongodb.client.model.Projections.excludeId;
42+
import static com.mongodb.client.model.Projections.fields;
43+
import static com.mongodb.client.model.Projections.include;
44+
import static com.mongodb.client.model.Sorts.ascending;
45+
import static com.mongodb.client.model.expressions.Expressions.current;
46+
import static com.mongodb.client.model.expressions.Expressions.of;
47+
import static com.mongodb.client.model.expressions.Expressions.ofArray;
48+
import static org.junit.jupiter.api.Assertions.assertEquals;
49+
50+
class InContextExpressionsFunctionalTest extends AbstractExpressionsFunctionalTest {
51+
52+
private MongoClient client;
53+
private MongoCollection<Document> col;
54+
55+
@BeforeEach
56+
public void setUp() {
57+
client = MongoClients.create();
58+
col = client.getDatabase("testdb").getCollection("testcol");
59+
col.drop();
60+
}
61+
62+
@AfterEach
63+
public void tearDown() {
64+
client.close();
65+
}
66+
67+
private static String bsonToString(final Bson project) {
68+
return project.toBsonDocument(Document.class, MongoClientSettings.getDefaultCodecRegistry()).toString().replaceAll("\"", "'");
69+
}
70+
71+
private List<Document> aggregate(final Bson... stages) {
72+
AggregateIterable<Document> result = col.aggregate(Arrays.asList(stages));
73+
List<Document> results = new ArrayList<>();
74+
result.forEach(r -> results.add(r));
75+
return results;
76+
}
77+
78+
@Test
79+
public void findTest() {
80+
col.insertMany(Arrays.asList(
81+
Document.parse("{_id: 1, x: 0, y: 2}"),
82+
Document.parse("{_id: 2, x: 0, y: 3}"),
83+
Document.parse("{_id: 3, x: 1, y: 3}")));
84+
85+
FindIterable<Document> iterable = col.find(expr(
86+
current().getInteger("x").eq(of(1))));
87+
List<Document> results = new ArrayList<>();
88+
iterable.forEach(r -> results.add(r));
89+
90+
assertEquals(
91+
Arrays.asList(Document.parse("{_id: 3, x: 1, y: 3}")),
92+
results);
93+
}
94+
95+
@Test
96+
public void matchTest() {
97+
col.insertMany(Arrays.asList(
98+
Document.parse("{_id: 1, x: 0, y: 2}"),
99+
Document.parse("{_id: 2, x: 0, y: 3}"),
100+
Document.parse("{_id: 3, x: 1, y: 3}")));
101+
102+
List<Document> results = aggregate(
103+
match(expr(current().getInteger("x").eq(of(1)))));
104+
105+
assertEquals(
106+
Arrays.asList(Document.parse("{_id: 3, x: 1, y: 3}")),
107+
results);
108+
}
109+
110+
@Test
111+
public void currentAsMapMatchTest() {
112+
col.insertMany(Arrays.asList(
113+
Document.parse("{_id: 1, x: 0, y: 2}"),
114+
Document.parse("{_id: 2, x: 0, y: 3}"),
115+
Document.parse("{_id: 3, x: 1, y: 3}")));
116+
117+
List<Document> results = aggregate(
118+
match(expr(Expressions.<NumberExpression>currentAsMap()
119+
.entrySet()
120+
.map(e -> e.getValue())
121+
.sum(v -> v).eq(of(7)))));
122+
123+
assertEquals(
124+
Arrays.asList(Document.parse("{_id: 3, x: 1, y: 3}")),
125+
results);
126+
}
127+
128+
@Test
129+
public void projectTest() {
130+
col.insertMany(Arrays.asList(
131+
Document.parse("{_id: 1, x: 0, y: 2}")));
132+
133+
List<Document> expected = Arrays.asList(Document.parse("{_id: 1, x: 0, c: 2}"));
134+
135+
// old, using "$y"
136+
Bson projectOld = project(fields(include("x"), computed("c",
137+
"$y")));
138+
assertEquals("{'$project': {'x': 1, 'c': '$y'}}", bsonToString(projectOld));
139+
assertEquals(expected,
140+
aggregate(projectOld));
141+
142+
// new, using current() with add/subtract
143+
Bson projectNew = project(fields(include("x"), computed("c",
144+
current().getInteger("y").add(10).subtract(10))));
145+
assertEquals(
146+
"{'$project': {'x': 1, 'c': "
147+
+ "{'$subtract': [{'$add': [{'$getField': "
148+
+ "{'input': '$$CURRENT', 'field': 'y'}}, 10]}, 10]}}}",
149+
bsonToString(projectNew));
150+
assertEquals(expected,
151+
aggregate(projectNew));
152+
}
153+
154+
@Test
155+
public void projectTest2() {
156+
col.insertMany(Arrays.asList(Document.parse("{_id: 0, x: 1}")));
157+
158+
// new, nestedArray
159+
Bson projectNestedArray = project(fields(excludeId(), computed("nestedArray", ofArray(
160+
current().getInteger("x").max(of(4)),
161+
current().getInteger("x"),
162+
of(0), of(1), of(true), of(false)
163+
))));
164+
assertEquals(
165+
Arrays.asList(Document.parse("{ nestedArray: [ 4, 1, 0, 1, true, false ] }")),
166+
aggregate(projectNestedArray));
167+
168+
// new, document
169+
Bson projectDocument = project(fields(computed("nested",
170+
// the below is roughly: "{ x: {$max : ['$x', 4] }}"
171+
of(Document.parse("{x: 9}")).setField("x", current().getInteger("x").max(of(4)))
172+
)));
173+
assertEquals(
174+
Arrays.asList(Document.parse("{_id: 0, nested: { x: 4 } }")),
175+
aggregate(projectDocument));
176+
}
177+
178+
@Test
179+
public void groupTest() {
180+
col.insertMany(Arrays.asList(
181+
Document.parse("{t: 0, a: 1}"),
182+
Document.parse("{t: 0, a: 2}"),
183+
Document.parse("{t: 1, a: 9}")));
184+
185+
List<Document> results = aggregate(
186+
Aggregates.group(
187+
current().getInteger("t").add(of(100)),
188+
sum("sum", current().getInteger("a").add(1))),
189+
Aggregates.sort(ascending("_id")));
190+
assertEquals(
191+
Arrays.asList(
192+
Document.parse("{_id: 100, sum: 5}"),
193+
Document.parse("{_id: 101, sum: 10}")),
194+
results);
195+
}
196+
}

0 commit comments

Comments
 (0)