/* * 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 com.mongodb.QueryBuilder.QueryBuilderException; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.regex.Pattern; import static com.mongodb.ClusterFixture.serverVersionAtLeast; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class QueryBuilderTest extends DatabaseTestCase { @Test public void elemMatchTest() { DBObject query = QueryBuilder.start("array").elemMatch( QueryBuilder.start("x").is(1).and("y").is(2).get()).get(); DBObject expected = new BasicDBObject("array", new BasicDBObject("$elemMatch", new BasicDBObject("x", 1).append("y", 2))); assertEquals(expected, query); // TODO: add integration test } @Test public void notTest() { Pattern pattern = Pattern.compile("\\w*"); DBObject query = QueryBuilder.start("x").not().regex(pattern).get(); DBObject expected = new BasicDBObject("x", new BasicDBObject("$not", pattern)); assertEquals(expected, query); query = QueryBuilder.start("x").not().regex(pattern).and("y").is("foo").get(); expected = new BasicDBObject("x", new BasicDBObject("$not", pattern)).append("y", "foo"); assertEquals(expected, query); query = QueryBuilder.start("x").not().greaterThan(2).get(); expected = new BasicDBObject("x", new BasicDBObject("$not", new BasicDBObject("$gt", 2))); assertEquals(expected, query); query = QueryBuilder.start("x").not().greaterThan(2).and("y").is("foo").get(); expected = new BasicDBObject("x", new BasicDBObject("$not", new BasicDBObject("$gt", 2))).append("y", "foo"); assertEquals(expected, query); query = QueryBuilder.start("x").not().greaterThan(2).lessThan(0).get(); expected = new BasicDBObject("x", new BasicDBObject("$not", new BasicDBObject("$gt", 2).append("$lt", 0))); assertEquals(expected, query); } @Test public void greaterThanTest() { String key = "x"; saveTestDocument(collection, key, 0); DBObject queryTrue = QueryBuilder.start(key).greaterThan(-1).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).greaterThan(0).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void greaterThanEqualsTest() { String key = "x"; saveTestDocument(collection, key, 0); DBObject queryTrue = QueryBuilder.start(key).greaterThanEquals(0).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryTrue2 = QueryBuilder.start(key).greaterThanEquals(-1).get(); assertTrue(testQuery(collection, queryTrue2)); DBObject queryFalse = QueryBuilder.start(key).greaterThanEquals(1).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void lessThanTest() { String key = "x"; saveTestDocument(collection, key, 0); DBObject queryTrue = QueryBuilder.start(key).lessThan(1).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).lessThan(0).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void lessThanEqualsTest() { String key = "x"; saveTestDocument(collection, key, 0); DBObject queryTrue = QueryBuilder.start(key).lessThanEquals(1).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryTrue2 = QueryBuilder.start(key).lessThanEquals(0).get(); assertTrue(testQuery(collection, queryTrue2)); DBObject queryFalse = QueryBuilder.start(key).lessThanEquals(-1).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void isTest() { String key = "x"; saveTestDocument(collection, key, "test"); DBObject queryTrue = QueryBuilder.start(key).is("test").get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).is("test1").get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void notEqualsTest() { String key = "x"; saveTestDocument(collection, key, "test"); DBObject queryTrue = QueryBuilder.start(key).notEquals("test1").get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).notEquals("test").get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void inTest() { String key = "x"; saveTestDocument(collection, key, 1); DBObject queryTrue = QueryBuilder.start(key).in(Arrays.asList(1, 2, 3)).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).in(Arrays.asList(2, 3, 4)).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void notInTest() { String key = "x"; saveTestDocument(collection, key, 1); DBObject queryTrue = QueryBuilder.start(key).notIn(Arrays.asList(2, 3, 4)).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).notIn(Arrays.asList(1, 2, 3)).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void modTest() { String key = "x"; saveTestDocument(collection, key, 9); DBObject queryTrue = QueryBuilder.start(key).mod(Arrays.asList(2, 1)).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).mod(Arrays.asList(2, 0)).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void allTest() { String key = "x"; saveTestDocument(collection, key, Arrays.asList(1, 2, 3)); DBObject query = QueryBuilder.start(key).all(Arrays.asList(1, 2, 3)).get(); assertTrue(testQuery(collection, query)); DBObject queryFalse = QueryBuilder.start(key).all(Arrays.asList(2, 3, 4)).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void sizeTest() { String key = "x"; saveTestDocument(collection, key, Arrays.asList(1, 2, 3)); DBObject queryTrue = QueryBuilder.start(key).size(3).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).size(4).get(); assertFalse(testQuery(collection, queryFalse)); DBObject queryFalse2 = QueryBuilder.start(key).size(2).get(); assertFalse(testQuery(collection, queryFalse2)); } @Test public void existsTest() { String key = "x"; saveTestDocument(collection, key, "test"); DBObject queryTrue = QueryBuilder.start(key).exists(true).get(); assertTrue(testQuery(collection, queryTrue)); DBObject queryFalse = QueryBuilder.start(key).exists(false).get(); assertFalse(testQuery(collection, queryFalse)); } @Test public void regexTest() { String key = "x"; saveTestDocument(collection, key, "test"); DBObject queryTrue = QueryBuilder.start(key).regex(Pattern.compile("\\w*")).get(); assertTrue(testQuery(collection, queryTrue)); } @Test public void rangeChainTest() { String key = "x"; saveTestDocument(collection, key, 2); DBObject queryTrue = QueryBuilder.start(key).greaterThan(0).lessThan(3).get(); assertTrue(testQuery(collection, queryTrue)); } @Test public void compoundChainTest() { String key = "x"; String key2 = "y"; String value = key; DBObject testDocument = new BasicDBObject(); testDocument.put(key, value); testDocument.put(key2, 9); collection.save(testDocument); DBObject queryTrue = QueryBuilder.start(key).is(value).and(key2).mod(Arrays.asList(2, 1)).get(); assertTrue(testQuery(collection, queryTrue)); } @Test public void arrayChainTest() { String key = "x"; saveTestDocument(collection, key, Arrays.asList(1, 2, 3)); DBObject queryTrue = QueryBuilder.start(key).all(Arrays.asList(1, 2, 3)).size(3).get(); assertTrue(testQuery(collection, queryTrue)); } @Test public void nearTest() { String key = "loc"; BasicDBObject geoSpatialIndex = new BasicDBObject(); geoSpatialIndex.put(key, "2d"); collection.createIndex(geoSpatialIndex); Double[] coordinates = {(double) 50, (double) 30}; saveTestDocument(collection, key, coordinates); DBObject queryTrue = QueryBuilder.start(key).near(45, 45).get(); DBObject expected = new BasicDBObject(key, new BasicDBObject("$near", Arrays.asList(45.0, 45.0))); assertEquals(queryTrue, expected); assertTrue(testQuery(collection, queryTrue)); queryTrue = QueryBuilder.start(key).near(45, 45, 16).get(); expected = new BasicDBObject(key, new BasicDBObject("$near", Arrays.asList(45.0, 45.0)) .append("$maxDistance", 16.0)); assertEquals(queryTrue, expected); assertTrue(testQuery(collection, queryTrue)); queryTrue = QueryBuilder.start(key).nearSphere(45, 45).get(); expected = new BasicDBObject(key, new BasicDBObject("$nearSphere", Arrays.asList(45.0, 45.0))); assertEquals(queryTrue, expected); assertTrue(testQuery(collection, queryTrue)); queryTrue = QueryBuilder.start(key).nearSphere(45, 45, 0.5).get(); expected = new BasicDBObject(key, new BasicDBObject("$nearSphere", Arrays.asList(45.0, 45.0)) .append("$maxDistance", 0.5)); assertEquals(queryTrue, expected); assertTrue(testQuery(collection, queryTrue)); queryTrue = QueryBuilder.start(key).withinCenterSphere(50, 30, 0.5).get(); assertTrue(testQuery(collection, queryTrue)); ArrayList<Double[]> points = new ArrayList<Double[]>(); points.add(new Double[]{(double) 30, (double) 30}); points.add(new Double[]{(double) 70, (double) 30}); points.add(new Double[]{(double) 70, (double) 30}); queryTrue = QueryBuilder.start(key).withinPolygon(points).get(); assertTrue(testQuery(collection, queryTrue)); } @Test(expected = IllegalArgumentException.class) public void shouldThrowExceptionNoPolygonGivenForWithinQuery() { QueryBuilder.start("loc").withinPolygon(null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowExceptionIfNoVerticesDefinedForPolygon() { QueryBuilder.start("loc").withinPolygon(new ArrayList<Double[]>()); } @Test(expected = IllegalArgumentException.class) public void shouldThrowExceptionIfInsufficientVerticesDefinedForPolygon() { QueryBuilder.start("loc").withinPolygon(Arrays.<Double[]>asList(new Double[]{30.0, 30.0})); } @Test public void textTest() { if (!serverVersionAtLeast(2, 6)) { return; } BasicDBObject enableTextCommand = new BasicDBObject("setParameter", 1).append("textSearchEnabled", true); database.getSisterDB("admin").command(enableTextCommand); DBCollection collection = database.getCollection("text-test"); BasicDBObject textIndex = new BasicDBObject("comments", "text"); collection.createIndex(textIndex); BasicDBObject doc = new BasicDBObject("comments", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") .append("meaning", 42); collection.save(doc); DBObject queryTrue = QueryBuilder.start().text("dolor").get(); DBObject expected = new BasicDBObject("$text", new BasicDBObject("$search", "dolor")); assertEquals(expected, queryTrue); assertTrue(testQuery(collection, queryTrue)); queryTrue = QueryBuilder.start().text("dolor", "english").get(); expected = new BasicDBObject("$text", new BasicDBObject("$search", "dolor").append("$language", "english")); assertEquals(expected, queryTrue); assertTrue(testQuery(collection, queryTrue)); queryTrue = QueryBuilder.start().and( QueryBuilder.start().text("dolor").get(), QueryBuilder.start("meaning").greaterThan(21).get()).get(); expected = new BasicDBObject("$and", Arrays.asList( new BasicDBObject("$text", new BasicDBObject("$search", "dolor")), new BasicDBObject("meaning", new BasicDBObject("$gt", 21)))); assertEquals(expected, queryTrue); assertTrue(testQuery(collection, queryTrue)); } @Test(expected = QueryBuilderException.class) public void shouldThrowAnExceptionIfTetIsNotAtTheTopLevelOfTheQuery() { QueryBuilder.start("x").text("funny"); } @Test public void failureTest() { boolean thrown = false; try { QueryBuilder.start("x").get(); } catch (QueryBuilderException e) { thrown = true; } assertTrue(thrown); boolean thrown2 = false; try { QueryBuilder.start("x").exists(true).and("y").get(); } catch (QueryBuilderException e) { thrown2 = true; } assertTrue(thrown2); boolean thrown3 = false; try { QueryBuilder.start("x").and("y").get(); } catch (QueryBuilderException e) { thrown3 = true; } assertTrue(thrown3); } @Test public void testOr() { collection.drop(); collection.insert(new BasicDBObject("a", 1)); collection.insert(new BasicDBObject("b", 1)); DBObject q = QueryBuilder.start().or(new BasicDBObject("a", 1), new BasicDBObject("b", 1)).get(); assertEquals(2, collection.find(q).count()); } @Test public void testAnd() { collection.drop(); collection.insert(new BasicDBObject("a", 1).append("b", 1)); collection.insert(new BasicDBObject("b", 1)); DBObject q = QueryBuilder.start().and(new BasicDBObject("a", 1), new BasicDBObject("b", 1)).get(); assertEquals(1, collection.find(q).count()); } @Test public void testMultipleAnd() { collection.drop(); collection.insert(new BasicDBObject("a", 1).append("b", 1)); collection.insert(new BasicDBObject("b", 1)); DBObject q = QueryBuilder.start().and(new BasicDBObject("a", 1), new BasicDBObject("b", 1)).get(); assertEquals(1, collection.find(q).count()); } /** * Convenience method that creates a new MongoDB Document with a key-value pair and saves it inside the specified collection * * @param collection Collection to save the new document to * @param key key of the field to be inserted to the new document * @param value value of the field to be inserted to the new document */ private void saveTestDocument(final DBCollection collection, final String key, final Object value) { DBObject testDocument = new BasicDBObject(); testDocument.put(key, value); collection.save(testDocument); } private boolean testQuery(final DBCollection collection, final DBObject query) { DBCursor cursor = collection.find(query); return cursor.hasNext(); } }