/src/main/com/mongodb/QueryBuilder.java

https://github.com/dixcychaitanya/mongo-java-driver · Java · 323 lines · 140 code · 34 blank · 149 comment · 11 complexity · e3737e31d09e8b334c8a79f47c5059df MD5 · raw file

  1. // QueryBuilder.java
  2. /**
  3. * Copyright (C) 2010 10gen Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.mongodb;
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.regex.Pattern;
  21. /**
  22. * Utility for creating DBObject queries
  23. * @author Julson Lim
  24. *
  25. */
  26. public class QueryBuilder {
  27. /**
  28. * Creates a builder with an empty query
  29. */
  30. public QueryBuilder() {
  31. _query = new BasicDBObject();
  32. }
  33. /**
  34. * returns a new QueryBuilder
  35. * @return
  36. */
  37. public static QueryBuilder start() {
  38. return new QueryBuilder();
  39. }
  40. /**
  41. * Creates a new query with a document key
  42. * @param key MongoDB document key
  43. * @return Returns a new QueryBuilder
  44. */
  45. public static QueryBuilder start(String key) {
  46. return (new QueryBuilder()).put(key);
  47. }
  48. /**
  49. * Adds a new key to the query if not present yet.
  50. * Sets this key as the current key.
  51. * @param key MongoDB document key
  52. * @return Returns the current QueryBuilder
  53. */
  54. public QueryBuilder put(String key) {
  55. _currentKey = key;
  56. if(_query.get(key) == null) {
  57. _query.put(_currentKey, new NullObject());
  58. }
  59. return this;
  60. }
  61. /**
  62. * Equivalent to <code>QueryBuilder.put(key)</code>. Intended for compound query chains to be more readable
  63. * Example: QueryBuilder.start("a").greaterThan(1).and("b").lessThan(3)
  64. * @param key MongoDB document key
  65. * @return Returns the current QueryBuilder with an appended key operand
  66. */
  67. public QueryBuilder and(String key) {
  68. return put(key);
  69. }
  70. /**
  71. * Equivalent to the $gt operator
  72. * @param object Value to query
  73. * @return Returns the current QueryBuilder with an appended "greater than" query
  74. */
  75. public QueryBuilder greaterThan(Object object) {
  76. addOperand(QueryOperators.GT, object);
  77. return this;
  78. }
  79. /**
  80. * Equivalent to the $gte operator
  81. * @param object Value to query
  82. * @return Returns the current QueryBuilder with an appended "greater than or equals" query
  83. */
  84. public QueryBuilder greaterThanEquals(Object object) {
  85. addOperand(QueryOperators.GTE, object);
  86. return this;
  87. }
  88. /**
  89. * Equivalent to the $lt operand
  90. * @param object Value to query
  91. * @return Returns the current QueryBuilder with an appended "less than" query
  92. */
  93. public QueryBuilder lessThan(Object object) {
  94. addOperand(QueryOperators.LT, object);
  95. return this;
  96. }
  97. /**
  98. * Equivalent to the $lte operand
  99. * @param object Value to query
  100. * @return Returns the current QueryBuilder with an appended "less than or equals" query
  101. */
  102. public QueryBuilder lessThanEquals(Object object) {
  103. addOperand(QueryOperators.LTE, object);
  104. return this;
  105. }
  106. /**
  107. * Equivalent of the find({key:value})
  108. * @param object Value to query
  109. * @return Returns the current QueryBuilder with an appended equality query
  110. */
  111. public QueryBuilder is(Object object) {
  112. addOperand(null, object);
  113. return this;
  114. }
  115. /**
  116. * Equivalent of the $ne operand
  117. * @param object Value to query
  118. * @return Returns the current QueryBuilder with an appended inequality query
  119. */
  120. public QueryBuilder notEquals(Object object) {
  121. addOperand(QueryOperators.NE, object);
  122. return this;
  123. }
  124. /**
  125. * Equivalent of the $in operand
  126. * @param object Value to query
  127. * @return Returns the current QueryBuilder with an appended "in array" query
  128. */
  129. public QueryBuilder in(Object object) {
  130. addOperand(QueryOperators.IN, object);
  131. return this;
  132. }
  133. /**
  134. * Equivalent of the $nin operand
  135. * @param object Value to query
  136. * @return Returns the current QueryBuilder with an appended "not in array" query
  137. */
  138. public QueryBuilder notIn(Object object) {
  139. addOperand(QueryOperators.NIN, object);
  140. return this;
  141. }
  142. /**
  143. * Equivalent of the $mod operand
  144. * @param object Value to query
  145. * @return Returns the current QueryBuilder with an appended modulo query
  146. */
  147. public QueryBuilder mod(Object object) {
  148. addOperand(QueryOperators.MOD, object);
  149. return this;
  150. }
  151. /**
  152. * Equivalent of the $all operand
  153. * @param object Value to query
  154. * @return Returns the current QueryBuilder with an appended "matches all array contents" query
  155. */
  156. public QueryBuilder all(Object object) {
  157. addOperand(QueryOperators.ALL, object);
  158. return this;
  159. }
  160. /**
  161. * Equivalent of the $size operand
  162. * @param object Value to query
  163. * @return Returns the current QueryBuilder with an appended size operator
  164. */
  165. public QueryBuilder size(Object object) {
  166. addOperand(QueryOperators.SIZE, object);
  167. return this;
  168. }
  169. /**
  170. * Equivalent of the $exists operand
  171. * @param object Value to query
  172. * @return Returns the current QueryBuilder with an appended exists operator
  173. */
  174. public QueryBuilder exists(Object object) {
  175. addOperand(QueryOperators.EXISTS, object);
  176. return this;
  177. }
  178. /**
  179. * Passes a regular expression for a query
  180. * @param regex Regex pattern object
  181. * @return Returns the current QueryBuilder with an appended regex query
  182. */
  183. public QueryBuilder regex(Pattern regex) {
  184. addOperand(null, regex);
  185. return this;
  186. }
  187. /**
  188. * Equivalent of the $within operand, used for geospatial operation
  189. * @param x x coordinate
  190. * @param y y coordinate
  191. * @param radius radius
  192. * @return
  193. */
  194. public QueryBuilder withinCenter( double x , double y , double radius ){
  195. addOperand( "$within" ,
  196. new BasicDBObject( "$center" , new Object[]{ new Double[]{ x , y } , radius } ) );
  197. return this;
  198. }
  199. /**
  200. * Equivalent of the $near operand
  201. * @param x x coordinate
  202. * @param y y coordinate
  203. * @return
  204. */
  205. public QueryBuilder near( double x , double y ){
  206. addOperand( "$near" ,
  207. new Double[]{ x , y } );
  208. return this;
  209. }
  210. /**
  211. * Equivalent of the $near operand
  212. * @param x x coordinate
  213. * @param y y coordinate
  214. * @param maxDistance max distance
  215. * @return
  216. */
  217. public QueryBuilder near( double x , double y , double maxDistance ){
  218. addOperand( "$near" ,
  219. new Double[]{ x , y , maxDistance } );
  220. return this;
  221. }
  222. /**
  223. * Equivalent to a $within operand, based on a bounding box using represented by two corners
  224. *
  225. * @param x the x coordinate of the first box corner.
  226. * @param y the y coordinate of the first box corner.
  227. * @param x2 the x coordinate of the second box corner.
  228. * @param y2 the y coordinate of the second box corner.
  229. * @return
  230. */
  231. public QueryBuilder withinBox(double x, double y, double x2, double y2) {
  232. addOperand( "$within" ,
  233. new BasicDBObject( "$box" , new Object[] { new Double[] { x, y }, new Double[] { x2, y2 } } ) );
  234. return this;
  235. }
  236. /**
  237. * Equivalent to a $or operand
  238. * @param ors
  239. * @return
  240. */
  241. @SuppressWarnings("unchecked")
  242. public QueryBuilder or( DBObject ... ors ){
  243. List l = (List)_query.get( "$or" );
  244. if ( l == null ){
  245. l = new ArrayList();
  246. _query.put( "$or" , l );
  247. }
  248. for ( DBObject o : ors )
  249. l.add( o );
  250. return this;
  251. }
  252. /**
  253. * Creates a <code>DBObject</code> query to be used for the driver's find operations
  254. * @return Returns a DBObject query instance
  255. * @throws RuntimeException if a key does not have a matching operand
  256. */
  257. public DBObject get() {
  258. for(String key : _query.keySet()) {
  259. if(_query.get(key) instanceof NullObject) {
  260. throw new QueryBuilderException("No operand for key:" + key);
  261. }
  262. }
  263. return _query;
  264. }
  265. private void addOperand(String op, Object value) {
  266. if(op == null) {
  267. _query.put(_currentKey, value);
  268. return;
  269. }
  270. Object storedValue = _query.get(_currentKey);
  271. BasicDBObject operand;
  272. if(!(storedValue instanceof DBObject)) {
  273. operand = new BasicDBObject();
  274. _query.put(_currentKey, operand);
  275. } else {
  276. operand = (BasicDBObject)_query.get(_currentKey);
  277. }
  278. operand.put(op, value);
  279. }
  280. @SuppressWarnings("serial")
  281. static class QueryBuilderException extends RuntimeException {
  282. QueryBuilderException(String message) {
  283. super(message);
  284. }
  285. }
  286. private static class NullObject {}
  287. private DBObject _query;
  288. private String _currentKey;
  289. }