com.mongodb.QueryBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongo-java-driver Show documentation
Show all versions of mongo-java-driver Show documentation
The MongoDB Java Driver uber-artifact, containing mongodb-driver, mongodb-driver-core, and bson
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mongodb;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
/**
* Utility for creating DBObject queries
*
* @mongodb.driver.manual tutorial/query-documents/ Querying
*/
public class QueryBuilder {
/**
* Creates a builder with an empty query
*/
public QueryBuilder() {
_query = new BasicDBObject();
}
/**
* Returns a new QueryBuilder.
*
* @return a builder
*/
public static QueryBuilder start() {
return new QueryBuilder();
}
/**
* Creates a new query with a document key
*
* @param key MongoDB document key
* @return {@code this}
*/
public static QueryBuilder start(String key) {
return (new QueryBuilder()).put(key);
}
/**
* Adds a new key to the query if not present yet. Sets this key as the current key.
*
* @param key MongoDB document key
* @return {@code this}
*/
public QueryBuilder put(String key) {
_currentKey = key;
if(_query.get(key) == null) {
_query.put(_currentKey, new NullObject());
}
return this;
}
/**
* Equivalent to {@code QueryBuilder.put(key)}. Intended for compound query chains to be more readable, e.g. {@code
* QueryBuilder.start("a").greaterThan(1).and("b").lessThan(3) }
*
* @param key MongoDB document key
* @return {@code this}
*/
public QueryBuilder and(String key) {
return put(key);
}
/**
* Equivalent to the $gt operator
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder greaterThan(Object object) {
addOperand(QueryOperators.GT, object);
return this;
}
/**
* Equivalent to the $gte operator
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder greaterThanEquals(Object object) {
addOperand(QueryOperators.GTE, object);
return this;
}
/**
* Equivalent to the $lt operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder lessThan(Object object) {
addOperand(QueryOperators.LT, object);
return this;
}
/**
* Equivalent to the $lte operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder lessThanEquals(Object object) {
addOperand(QueryOperators.LTE, object);
return this;
}
/**
* Equivalent of the find({key:value})
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder is(Object object) {
addOperand(null, object);
return this;
}
/**
* Equivalent of the $ne operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder notEquals(Object object) {
addOperand(QueryOperators.NE, object);
return this;
}
/**
* Equivalent of the $in operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder in(Object object) {
addOperand(QueryOperators.IN, object);
return this;
}
/**
* Equivalent of the $nin operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder notIn(Object object) {
addOperand(QueryOperators.NIN, object);
return this;
}
/**
* Equivalent of the $mod operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder mod(Object object) {
addOperand(QueryOperators.MOD, object);
return this;
}
/**
* Equivalent of the $all operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder all(Object object) {
addOperand(QueryOperators.ALL, object);
return this;
}
/**
* Equivalent of the $size operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder size(Object object) {
addOperand(QueryOperators.SIZE, object);
return this;
}
/**
* Equivalent of the $exists operand
*
* @param object Value to query
* @return {@code this}
*/
public QueryBuilder exists(Object object) {
addOperand(QueryOperators.EXISTS, object);
return this;
}
/**
* Passes a regular expression for a query
*
* @param regex Regex pattern object
* @return {@code this}
*/
public QueryBuilder regex(Pattern regex) {
addOperand(null, regex);
return this;
}
/**
* Equivalent to the $elemMatch operand
*
* @param match the object to match
* @return {@code this}
*/
public QueryBuilder elemMatch(final DBObject match) {
addOperand(QueryOperators.ELEM_MATCH, match);
return this;
}
/**
* Equivalent of the $within operand, used for geospatial operation
*
* @param x x coordinate
* @param y y coordinate
* @param radius radius
* @return {@code this}
*/
public QueryBuilder withinCenter( double x , double y , double radius ){
addOperand( QueryOperators.WITHIN ,
new BasicDBObject(QueryOperators.CENTER, new Object[]{ new Double[]{ x , y } , radius } ) );
return this;
}
/**
* Equivalent of the $near operand
*
* @param x x coordinate
* @param y y coordinate
* @return {@code this}
*/
public QueryBuilder near( double x , double y ){
addOperand( QueryOperators.NEAR,
Arrays.asList(x, y));
return this;
}
/**
* Equivalent of the $near operand
*
* @param x x coordinate
* @param y y coordinate
* @param maxDistance max distance
* @return {@code this}
*/
public QueryBuilder near( double x , double y , double maxDistance ){
addOperand( QueryOperators.NEAR ,
Arrays.asList(x, y));
addOperand( QueryOperators.MAX_DISTANCE ,
maxDistance );
return this;
}
/**
* Equivalent of the $nearSphere operand
*
* @param longitude coordinate in decimal degrees
* @param latitude coordinate in decimal degrees
* @return {@code this}
*/
public QueryBuilder nearSphere( double longitude , double latitude ){
addOperand( QueryOperators.NEAR_SPHERE,
Arrays.asList(longitude, latitude));
return this;
}
/**
* Equivalent of the $nearSphere operand
*
* @param longitude coordinate in decimal degrees
* @param latitude coordinate in decimal degrees
* @param maxDistance max spherical distance
* @return {@code this}
*/
public QueryBuilder nearSphere( double longitude , double latitude , double maxDistance ){
addOperand( QueryOperators.NEAR_SPHERE ,
Arrays.asList(longitude, latitude));
addOperand( QueryOperators.MAX_DISTANCE ,
maxDistance );
return this;
}
/**
* Equivalent of the $centerSphere operand mostly intended for queries up to a few hundred miles or km.
*
* @param longitude coordinate in decimal degrees
* @param latitude coordinate in decimal degrees
* @param maxDistance max spherical distance
* @return {@code this}
*/
public QueryBuilder withinCenterSphere( double longitude , double latitude , double maxDistance ){
addOperand( QueryOperators.WITHIN ,
new BasicDBObject(QueryOperators.CENTER_SPHERE, new Object[]{ new Double[]{longitude , latitude} , maxDistance } ) );
return this;
}
/**
* Equivalent to a $within operand, based on a bounding box using represented by two corners
*
* @param x the x coordinate of the first box corner.
* @param y the y coordinate of the first box corner.
* @param x2 the x coordinate of the second box corner.
* @param y2 the y coordinate of the second box corner.
* @return {@code this}
*/
public QueryBuilder withinBox(double x, double y, double x2, double y2) {
addOperand( QueryOperators.WITHIN ,
new BasicDBObject(QueryOperators.BOX, new Object[] { new Double[] { x, y }, new Double[] { x2, y2 } } ) );
return this;
}
/**
* Equivalent to a $within operand, based on a bounding polygon represented by an array of points
*
* @param points an array of Double[] defining the vertices of the search area
* @return this
*/
public QueryBuilder withinPolygon(List points) {
if(points == null || points.isEmpty() || points.size() < 3)
throw new IllegalArgumentException("Polygon insufficient number of vertices defined");
addOperand( QueryOperators.WITHIN ,
new BasicDBObject(QueryOperators.POLYGON, points ) );
return this;
}
/**
* Equivalent to a $text operand.
*
* @param search the search terms to apply to the text index.
* @return {@code this}
* @mongodb.server.release 2.6
*/
public QueryBuilder text(String search) {
return text(search, null);
}
/**
* Equivalent to a $text operand.
*
* @param search the search terms to apply to the text index.
* @param language the language to use.
* @return {@code this}
* @mongodb.server.release 2.6
*/
public QueryBuilder text(String search, String language) {
if(_currentKey != null) {
throw new QueryBuilderException("The text operand may only occur at the top-level of a query. It does" +
" not apply to a specific element, but rather to a document as a whole.");
}
put(QueryOperators.TEXT);
addOperand(QueryOperators.SEARCH, search);
if(language != null) {
addOperand(QueryOperators.LANGUAGE, language);
}
return this;
}
/**
* Equivalent to $not meta operator. Must be followed by an operand, not a value, e.g. {@code
* QueryBuilder.start("val").not().mod(Arrays.asList(10, 1)) }
*
* @return {@code this}
*/
public QueryBuilder not() {
_hasNot = true;
return this;
}
/**
* Equivalent to an $or operand
*
* @param ors the list of conditions to or together
* @return {@code this}
*/
@SuppressWarnings("unchecked")
public QueryBuilder or( DBObject ... ors ){
List l = (List)_query.get( QueryOperators.OR );
if ( l == null ){
l = new ArrayList();
_query.put( QueryOperators.OR , l );
}
Collections.addAll(l, ors);
return this;
}
/**
* Equivalent to an $and operand
*
* @param ands the list of conditions to and together
* @return {@code this}
*/
@SuppressWarnings("unchecked")
public QueryBuilder and( DBObject ... ands ){
List l = (List)_query.get( QueryOperators.AND );
if ( l == null ){
l = new ArrayList();
_query.put( QueryOperators.AND , l );
}
Collections.addAll(l, ands);
return this;
}
/**
* Creates a {@code DBObject} query to be used for the driver's find operations
*
* @return {@code this}
* @throws QueryBuilderException if a key does not have a matching operand
*/
public DBObject get() {
for(String key : _query.keySet()) {
if(_query.get(key) instanceof NullObject) {
throw new QueryBuilderException("No operand for key:" + key);
}
}
return _query;
}
private void addOperand(String op, Object value) {
if(op == null) {
if (_hasNot) {
value = new BasicDBObject(QueryOperators.NOT, value);
_hasNot = false;
}
_query.put(_currentKey, value);
return;
}
Object storedValue = _query.get(_currentKey);
BasicDBObject operand;
if(!(storedValue instanceof DBObject)) {
operand = new BasicDBObject();
if (_hasNot) {
DBObject notOperand = new BasicDBObject(QueryOperators.NOT, operand);
_query.put(_currentKey, notOperand);
_hasNot = false;
} else {
_query.put(_currentKey, operand);
}
} else {
operand = (BasicDBObject)_query.get(_currentKey);
if (operand.get(QueryOperators.NOT) != null) {
operand = (BasicDBObject) operand.get(QueryOperators.NOT);
}
}
operand.put(op, value);
}
@SuppressWarnings("serial")
static class QueryBuilderException extends RuntimeException {
QueryBuilderException(String message) {
super(message);
}
}
private static class NullObject {}
private DBObject _query;
private String _currentKey;
private boolean _hasNot;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy