23
23
package com .mongodb ;
24
24
25
25
import java .util .ArrayList ;
26
+ import java .util .Collections ;
26
27
import java .util .List ;
27
28
import java .util .regex .Pattern ;
28
29
32
33
*
33
34
*/
34
35
public class QueryBuilder {
35
-
36
+
36
37
/**
37
38
* Creates a builder with an empty query
38
39
*/
@@ -61,7 +62,7 @@ public static QueryBuilder start(String key) {
61
62
* Adds a new key to the query if not present yet.
62
63
* Sets this key as the current key.
63
64
* @param key MongoDB document key
64
- * @return Returns the current QueryBuilder
65
+ * @return this
65
66
*/
66
67
public QueryBuilder put (String key ) {
67
68
_currentKey = key ;
@@ -72,10 +73,10 @@ public QueryBuilder put(String key) {
72
73
}
73
74
74
75
/**
75
- * Equivalent to <code>QueryBuilder.put(key)</code>. Intended for compound query chains to be more readable
76
- * Example: QueryBuilder.start("a").greaterThan(1).and("b").lessThan(3)
76
+ * Equivalent to <code>QueryBuilder.put(key)</code>. Intended for compound query chains to be more readable, e.g.
77
+ * {@code QueryBuilder.start("a").greaterThan(1).and("b").lessThan(3) }
77
78
* @param key MongoDB document key
78
- * @return Returns the current QueryBuilder with an appended key operand
79
+ * @return this
79
80
*/
80
81
public QueryBuilder and (String key ) {
81
82
return put (key );
@@ -210,7 +211,19 @@ public QueryBuilder regex(Pattern regex) {
210
211
addOperand (null , regex );
211
212
return this ;
212
213
}
213
-
214
+
215
+ /**
216
+ * Equivalent to the $elemMatch operand
217
+ * @param match the object to match
218
+ * @return Returns the current QueryBuilder with an appended elemMatch operator
219
+ */
220
+ public QueryBuilder elemMatch (final DBObject match ) {
221
+ addOperand (QueryOperators .ELEM_MATCH , match );
222
+ return this ;
223
+ }
224
+
225
+
226
+
214
227
/**
215
228
* Equivalent of the $within operand, used for geospatial operation
216
229
* @param x x coordinate
@@ -219,8 +232,8 @@ public QueryBuilder regex(Pattern regex) {
219
232
* @return
220
233
*/
221
234
public QueryBuilder withinCenter ( double x , double y , double radius ){
222
- addOperand ( "$within" ,
223
- new BasicDBObject ( "$center" , new Object []{ new Double []{ x , y } , radius } ) );
235
+ addOperand ( QueryOperators . WITHIN ,
236
+ new BasicDBObject (QueryOperators . CENTER , new Object []{ new Double []{ x , y } , radius } ) );
224
237
return this ;
225
238
}
226
239
@@ -231,7 +244,7 @@ public QueryBuilder withinCenter( double x , double y , double radius ){
231
244
* @return
232
245
*/
233
246
public QueryBuilder near ( double x , double y ){
234
- addOperand ( "$near" ,
247
+ addOperand (QueryOperators . NEAR ,
235
248
new Double []{ x , y } );
236
249
return this ;
237
250
}
@@ -244,7 +257,7 @@ public QueryBuilder near( double x , double y ){
244
257
* @return
245
258
*/
246
259
public QueryBuilder near ( double x , double y , double maxDistance ){
247
- addOperand ( "$near" ,
260
+ addOperand ( QueryOperators . NEAR ,
248
261
new Double []{ x , y , maxDistance } );
249
262
return this ;
250
263
}
@@ -256,7 +269,7 @@ public QueryBuilder near( double x , double y , double maxDistance ){
256
269
* @return
257
270
*/
258
271
public QueryBuilder nearSphere ( double longitude , double latitude ){
259
- addOperand ( "$nearSphere" ,
272
+ addOperand (QueryOperators . NEAR_SPHERE ,
260
273
new Double []{ longitude , latitude } );
261
274
return this ;
262
275
}
@@ -269,7 +282,7 @@ public QueryBuilder nearSphere( double longitude , double latitude ){
269
282
* @return
270
283
*/
271
284
public QueryBuilder nearSphere ( double longitude , double latitude , double maxDistance ){
272
- addOperand ( "$nearSphere" ,
285
+ addOperand ( QueryOperators . NEAR_SPHERE ,
273
286
new Double []{ longitude , latitude , maxDistance } );
274
287
return this ;
275
288
}
@@ -283,8 +296,8 @@ public QueryBuilder nearSphere( double longitude , double latitude , double maxD
283
296
* @return
284
297
*/
285
298
public QueryBuilder withinCenterSphere ( double longitude , double latitude , double maxDistance ){
286
- addOperand ( "$within" ,
287
- new BasicDBObject ( "$centerSphere" , new Object []{ new Double []{longitude , latitude } , maxDistance } ) );
299
+ addOperand ( QueryOperators . WITHIN ,
300
+ new BasicDBObject (QueryOperators . CENTER_SPHERE , new Object []{ new Double []{longitude , latitude } , maxDistance } ) );
288
301
return this ;
289
302
}
290
303
@@ -298,56 +311,65 @@ public QueryBuilder withinCenterSphere( double longitude , double latitude , dou
298
311
* @return
299
312
*/
300
313
public QueryBuilder withinBox (double x , double y , double x2 , double y2 ) {
301
- addOperand ( "$within" ,
302
- new BasicDBObject ( "$box" , new Object [] { new Double [] { x , y }, new Double [] { x2 , y2 } } ) );
314
+ addOperand ( QueryOperators . WITHIN ,
315
+ new BasicDBObject (QueryOperators . BOX , new Object [] { new Double [] { x , y }, new Double [] { x2 , y2 } } ) );
303
316
return this ;
304
317
}
305
318
306
319
/**
307
320
* Equivalent to a $within operand, based on a bounding polygon represented by an array of points
308
321
*
309
322
* @param points an array of Double[] defining the vertices of the search area
310
- * @return
323
+ * @return this
311
324
*/
312
325
public QueryBuilder withinPolygon (List <Double []> points ) {
313
326
if (points == null || points .isEmpty () || points .size () < 3 )
314
327
throw new IllegalArgumentException ("Polygon insufficient number of vertices defined" );
315
- addOperand ( "$within" ,
316
- new BasicDBObject ( "$polygon" , points ) );
328
+ addOperand ( QueryOperators . WITHIN ,
329
+ new BasicDBObject (QueryOperators . POLYGON , points ) );
317
330
return this ;
318
331
}
319
332
320
333
/**
321
- * Equivalent to a $or operand
322
- * @param ors
323
- * @return
334
+ * Equivalent to $not meta operator. Must be followed by an operand, not a value, e.g.
335
+ * {@code QueryBuilder.start("val").not().mod(Arrays.asList(10, 1)) }
336
+ *
337
+ * @return Returns the current QueryBuilder with an appended "not" meta operator
338
+ */
339
+ public QueryBuilder not () {
340
+ _hasNot = true ;
341
+ return this ;
342
+ }
343
+
344
+ /**
345
+ * Equivalent to an $or operand
346
+ * @param ors the list of conditions to or together
347
+ * @return Returns the current QueryBuilder with appended "or" operator
324
348
*/
325
349
@ SuppressWarnings ("unchecked" )
326
350
public QueryBuilder or ( DBObject ... ors ){
327
- List l = (List )_query .get ( "$or" );
351
+ List l = (List )_query .get ( QueryOperators . OR );
328
352
if ( l == null ){
329
353
l = new ArrayList ();
330
- _query .put ( "$or" , l );
354
+ _query .put ( QueryOperators . OR , l );
331
355
}
332
- for ( DBObject o : ors )
333
- l .add ( o );
356
+ Collections .addAll (l , ors );
334
357
return this ;
335
358
}
336
359
337
360
/**
338
361
* Equivalent to an $and operand
339
- * @param ands
340
- * @return
362
+ * @param ands the list of conditions to and together
363
+ * @return Returns the current QueryBuilder with appended "and" operator
341
364
*/
342
365
@ SuppressWarnings ("unchecked" )
343
366
public QueryBuilder and ( DBObject ... ands ){
344
- List l = (List )_query .get ( "$and" );
367
+ List l = (List )_query .get ( QueryOperators . AND );
345
368
if ( l == null ){
346
369
l = new ArrayList ();
347
- _query .put ( "$and" , l );
370
+ _query .put ( QueryOperators . AND , l );
348
371
}
349
- for ( DBObject o : ands )
350
- l .add ( o );
372
+ Collections .addAll (l , ands );
351
373
return this ;
352
374
}
353
375
@@ -367,6 +389,10 @@ public DBObject get() {
367
389
368
390
private void addOperand (String op , Object value ) {
369
391
if (op == null ) {
392
+ if (_hasNot ) {
393
+ value = new BasicDBObject (QueryOperators .NOT , value );
394
+ _hasNot = false ;
395
+ }
370
396
_query .put (_currentKey , value );
371
397
return ;
372
398
}
@@ -375,13 +401,21 @@ private void addOperand(String op, Object value) {
375
401
BasicDBObject operand ;
376
402
if (!(storedValue instanceof DBObject )) {
377
403
operand = new BasicDBObject ();
378
- _query .put (_currentKey , operand );
404
+ if (_hasNot ) {
405
+ DBObject notOperand = new BasicDBObject (QueryOperators .NOT , operand );
406
+ _query .put (_currentKey , notOperand );
407
+ _hasNot = false ;
408
+ } else {
409
+ _query .put (_currentKey , operand );
410
+ }
379
411
} else {
380
412
operand = (BasicDBObject )_query .get (_currentKey );
413
+ if (operand .get (QueryOperators .NOT ) != null ) {
414
+ operand = (BasicDBObject ) operand .get (QueryOperators .NOT );
415
+ }
381
416
}
382
417
operand .put (op , value );
383
418
}
384
-
385
419
@ SuppressWarnings ("serial" )
386
420
static class QueryBuilderException extends RuntimeException {
387
421
QueryBuilderException (String message ) {
@@ -392,5 +426,6 @@ private static class NullObject {}
392
426
393
427
private DBObject _query ;
394
428
private String _currentKey ;
429
+ private boolean _hasNot ;
395
430
396
431
}
0 commit comments