@ -15,18 +15,13 @@
@@ -15,18 +15,13 @@
* /
package org.springframework.data.mongodb.core.query ;
import static org.hamcrest.CoreMatchers.* ;
import static org.junit.Assert.* ;
import static org.assertj.core.api.Assertions.* ;
import static org.springframework.data.mongodb.core.query.Criteria.* ;
import static org.springframework.data.mongodb.core.query.Query.* ;
import java.util.Arrays ;
import org.bson.Document ;
import org.junit.Assert ;
import org.junit.Rule ;
import org.junit.Test ;
import org.junit.rules.ExpectedException ;
import org.springframework.data.domain.Sort ;
import org.springframework.data.domain.Sort.Direction ;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException ;
@ -44,41 +39,40 @@ import org.springframework.data.mongodb.core.SpecialDoc;
@@ -44,41 +39,40 @@ import org.springframework.data.mongodb.core.SpecialDoc;
* /
public class QueryTests {
@Rule public ExpectedException exception = ExpectedException . none ( ) ;
@Test
public void testSimpleQuery ( ) {
Query q = new Query ( where ( "name" ) . is ( "Thomas" ) . and ( "age" ) . lt ( 80 ) ) ;
Document expected = Document . parse ( "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document . parse ( "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}" ) ) ;
}
@Test
public void testQueryWithNot ( ) {
Query q = new Query ( where ( "name" ) . is ( "Thomas" ) . and ( "age" ) . not ( ) . mod ( 10 , 0 ) ) ;
Document expected = Document . parse ( "{ \"name\" : \"Thomas\" , \"age\" : { \"$not\" : { \"$mod\" : [ 10 , 0]}}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) )
. isEqualTo ( Document . parse ( "{ \"name\" : \"Thomas\" , \"age\" : { \"$not\" : { \"$mod\" : [ 10 , 0]}}}" ) ) ;
}
@Test
public void testInvalidQueryWithNotIs ( ) {
try {
new Query ( where ( "name" ) . not ( ) . is ( "Thomas" ) ) ;
Assert . fail ( "This should have caused an InvalidDocumentStoreApiUsageException" ) ;
} catch ( InvalidMongoDbApiUsageException e ) { }
assertThatExceptionOfType ( InvalidMongoDbApiUsageException . class )
. isThrownBy ( ( ) - > new Query ( where ( "name" ) . not ( ) . is ( "Thomas" ) ) ) ;
}
@Test
public void testOrQuery ( ) {
Query q = new Query ( new Criteria ( ) . orOperator ( where ( "name" ) . is ( "Sven" ) . and ( "age" ) . lt ( 50 ) , where ( "age" ) . lt ( 50 ) ,
where ( "name" ) . is ( "Thomas" ) ) ) ;
Document expected = Document . parse (
"{ \"$or\" : [ { \"name\" : \"Sven\" , \"age\" : { \"$lt\" : 50}} , { \"age\" : { \"$lt\" : 50}} , { \"name\" : \"Thomas\"}]}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document . parse (
"{ \"$or\" : [ { \"name\" : \"Sven\" , \"age\" : { \"$lt\" : 50}} , { \"age\" : { \"$lt\" : 50}} , { \"name\" : \"Thomas\"}]}" ) ) ;
}
@Test
public void testAndQuery ( ) {
Query q = new Query ( new Criteria ( ) . andOperator ( where ( "name" ) . is ( "Sven" ) , where ( "age" ) . lt ( 50 ) ) ) ;
Document expected = Document . parse ( "{ \"$and\" : [ { \"name\" : \"Sven\"} , { \"age\" : { \"$lt\" : 50}}]}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
@ -86,33 +80,35 @@ public class QueryTests {
@@ -86,33 +80,35 @@ public class QueryTests {
@Test
public void testNorQuery ( ) {
Query q = new Query (
new Criteria ( ) . norOperator ( where ( "name" ) . is ( "Sven" ) , where ( "age" ) . lt ( 50 ) , where ( "name" ) . is ( "Thomas" ) ) ) ;
Document expected = Document
. parse ( "{ \"$nor\" : [ { \"name\" : \"Sven\"} , { \"age\" : { \"$lt\" : 50}} , { \"name\" : \"Thomas\"}]}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document
. parse ( "{ \"$nor\" : [ { \"name\" : \"Sven\"} , { \"age\" : { \"$lt\" : 50}} , { \"name\" : \"Thomas\"}]}" ) ) ;
}
@Test
public void testQueryWithLimit ( ) {
Query q = new Query ( where ( "name" ) . gte ( "M" ) . lte ( "T" ) . and ( "age" ) . not ( ) . gt ( 22 ) ) ;
q . limit ( 50 ) ;
Document expected = Document
. parse ( "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document
. parse ( "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}" ) ) ;
Assert . assertEquals ( 50 , q . getLimit ( ) ) ;
}
@Test
public void testQueryWithFieldsAndSlice ( ) {
Query q = new Query ( where ( "name" ) . gte ( "M" ) . lte ( "T" ) . and ( "age" ) . not ( ) . gt ( 22 ) ) ;
q . fields ( ) . exclude ( "address" ) . include ( "name" ) . slice ( "orders" , 10 ) ;
Document expected = Document
. parse ( "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
Document expectedFields = Document . parse ( "{ \"address\" : 0 , \"name\" : 1 , \"orders\" : { \"$slice\" : 10}}" ) ;
Assert . assertEquals ( expectedFields , q . getFieldsObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document
. parse ( "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}" ) ) ;
assertThat ( q . getFieldsObject ( ) )
. isEqualTo ( Document . parse ( "{ \"address\" : 0 , \"name\" : 1 , \"orders\" : { \"$slice\" : 10}}" ) ) ;
}
@Test // DATAMONGO-652
@ -121,87 +117,87 @@ public class QueryTests {
@@ -121,87 +117,87 @@ public class QueryTests {
Query query = query ( where ( "name" ) . gte ( "M" ) . lte ( "T" ) . and ( "age" ) . not ( ) . gt ( 22 ) ) ;
query . fields ( ) . elemMatch ( "products" , where ( "name" ) . is ( "milk" ) ) . position ( "comments" , 2 ) ;
Document expected = Document
. parse ( "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}" ) ;
assertThat ( query . getQueryObject ( ) , is ( expected ) ) ;
Document expectedFields = Document
. parse ( "{ \"products\" : { \"$elemMatch\" : { \"name\" : \"milk\"}} , \"comments.$\" : 2}" ) ;
assertThat ( query . getFieldsObject ( ) , is ( expectedFields ) ) ;
assertThat ( query . getQueryObject ( ) ) . isEqualTo ( Document
. parse ( "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}" ) ) ;
assertThat ( query . getFieldsObject ( ) )
. isEqualTo ( Document . parse ( "{ \"products\" : { \"$elemMatch\" : { \"name\" : \"milk\"}} , \"comments.$\" : 2}" ) ) ;
}
@Test
public void testSimpleQueryWithChainedCriteria ( ) {
Query q = new Query ( where ( "name" ) . is ( "Thomas" ) . and ( "age" ) . lt ( 80 ) ) ;
Document expected = Document . parse ( "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document . parse ( "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}" ) ) ;
}
@Test
public void testComplexQueryWithMultipleChainedCriteria ( ) {
Query q = new Query (
where ( "name" ) . regex ( "^T.*" ) . and ( "age" ) . gt ( 20 ) . lt ( 80 ) . and ( "city" ) . in ( "Stockholm" , "London" , "New York" ) ) ;
Document expected = Document
. parse ( "{ \"name\" : { \"$regex\" : \"^T.*\", \"$options\" : \"\" } , \"age\" : { \"$gt\" : 20 , \"$lt\" : 80} , "
+ "\"city\" : { \"$in\" : [ \"Stockholm\" , \"London\" , \"New York\"]}}" ) ;
Assert . assertEquals ( expected . toJson ( ) , q . getQueryObject ( ) . toJson ( ) ) ;
assertThat ( q . getQueryObject ( ) . toJson ( ) ) . isEqualTo ( Document . parse (
"{ \"name\" : { \"$regex\" : \"^T.*\", \"$options\" : \"\" } , \"age\" : { \"$gt\" : 20 , \"$lt\" : 80} , "
+ "\"city\" : { \"$in\" : [ \"Stockholm\" , \"London\" , \"New York\"]}}" )
. toJson ( ) ) ;
}
@Test
public void testAddCriteriaWithComplexQueryWithMultipleChainedCriteria ( ) {
Query q1 = new Query (
where ( "name" ) . regex ( "^T.*" ) . and ( "age" ) . gt ( 20 ) . lt ( 80 ) . and ( "city" ) . in ( "Stockholm" , "London" , "New York" ) ) ;
Query q2 = new Query ( where ( "name" ) . regex ( "^T.*" ) . and ( "age" ) . gt ( 20 ) . lt ( 80 ) )
. addCriteria ( where ( "city" ) . in ( "Stockholm" , "London" , "New York" ) ) ;
Assert . assertEquals ( q1 . getQueryObject ( ) . toString ( ) , q2 . getQueryObject ( ) . toString ( ) ) ;
assertThat ( q1 . getQueryObject ( ) . toString ( ) ) . isEqualTo ( q2 . getQueryObject ( ) . toString ( ) ) ;
Query q3 = new Query ( where ( "name" ) . regex ( "^T.*" ) ) . addCriteria ( where ( "age" ) . gt ( 20 ) . lt ( 80 ) )
. addCriteria ( where ( "city" ) . in ( "Stockholm" , "London" , "New York" ) ) ;
Assert . assertEquals ( q1 . getQueryObject ( ) . toString ( ) , q3 . getQueryObject ( ) . toString ( ) ) ;
assertThat ( q1 . getQueryObject ( ) . toString ( ) ) . isEqualTo ( q3 . getQueryObject ( ) . toString ( ) ) ;
}
@Test
public void testQueryWithElemMatch ( ) {
Query q = new Query ( where ( "openingHours" ) . elemMatch ( where ( "dayOfWeek" ) . is ( "Monday" ) . and ( "open" ) . lte ( "1800" ) ) ) ;
Document expected = Document . parse (
"{ \"openingHours\" : { \"$elemMatch\" : { \"dayOfWeek\" : \"Monday\" , \"open\" : { \"$lte\" : \"1800\"}}}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document . parse (
"{ \"openingHours\" : { \"$elemMatch\" : { \"dayOfWeek\" : \"Monday\" , \"open\" : { \"$lte\" : \"1800\"}}}}" ) ) ;
}
@Test
public void testQueryWithIn ( ) {
Query q = new Query ( where ( "state" ) . in ( "NY" , "NJ" , "PA" ) ) ;
Document expected = Document . parse ( "{ \"state\" : { \"$in\" : [ \"NY\" , \"NJ\" , \"PA\"]}}" ) ;
Assert . assertEquals ( expected , q . getQueryObject ( ) ) ;
assertThat ( q . getQueryObject ( ) ) . isEqualTo ( Document . parse ( "{ \"state\" : { \"$in\" : [ \"NY\" , \"NJ\" , \"PA\"]}}" ) ) ;
}
@Test
public void testQueryWithRegex ( ) {
Query q = new Query ( where ( "name" ) . regex ( "b.*" ) ) ;
Document expected = Document . parse ( "{ \"name\" : { \"$regex\" : \"b.*\", \"$options\" : \"\" }}" ) ;
Assert . assertEquals ( expected . toJson ( ) , q . getQueryObject ( ) . toJson ( ) ) ;
assertThat ( q . getQueryObject ( ) . toJson ( ) )
. isEqualTo ( Document . parse ( "{ \"name\" : { \"$regex\" : \"b.*\", \"$options\" : \"\" }}" ) . toJson ( ) ) ;
}
@Test
public void testQueryWithRegexAndOption ( ) {
Query q = new Query ( where ( "name" ) . regex ( "b.*" , "i" ) ) ;
Document expected = Document . parse ( "{ \"name\" : { \"$regex\" : \"b.*\" , \"$options\" : \"i\"}}" ) ;
Assert . assertEquals ( expected . toJson ( ) , q . getQueryObject ( ) . toJson ( ) ) ;
assertThat ( q . getQueryObject ( ) . toJson ( ) )
. isEqualTo ( Document . parse ( "{ \"name\" : { \"$regex\" : \"b.*\" , \"$options\" : \"i\"}}" ) . toJson ( ) ) ;
}
@Test // DATAMONGO-538
public void addsSortCorrectly ( ) {
Query query = new Query ( ) . with ( Sort . by ( Direction . DESC , "foo" ) ) ;
assertThat ( query . getSortObject ( ) , is ( Document . parse ( "{ \"foo\" : -1}" ) ) ) ;
assertThat ( query . getSortObject ( ) ) . isEqualTo ( Document . parse ( "{ \"foo\" : -1}" ) ) ;
}
@Test
public void rejectsOrderWithIgnoreCase ( ) {
exception . expect ( IllegalArgumentException . class ) ;
exception . expectMessage ( "foo" ) ;
new Query ( ) . with ( Sort . by ( new Sort . Order ( "foo" ) . ignoreCase ( ) ) ) ;
assertThatExceptionOfType ( IllegalArgumentException . class )
. isThrownBy ( ( ) - > new Query ( ) . with ( Sort . by ( new Sort . Order ( "foo" ) . ignoreCase ( ) ) ) ) ;
}
@Test // DATAMONGO-709, DATAMONGO-1735, // DATAMONGO-2198
@ -210,21 +206,20 @@ public class QueryTests {
@@ -210,21 +206,20 @@ public class QueryTests {
Query query = new Query ( where ( "name" ) . is ( "foo" ) ) . restrict ( SpecialDoc . class ) ;
assertThat ( query . getRestrictedTypes ( ) , is ( notNullValue ( ) ) ) ;
assertThat ( query . getRestrictedTypes ( ) . size ( ) , is ( 1 ) ) ;
assertThat ( query . getRestrictedTypes ( ) , hasItems ( Arrays . asList ( SpecialDoc . class ) . toArray ( new Class < ? > [ 0 ] ) ) ) ;
assertThat ( query . getRestrictedTypes ( ) ) . containsExactly ( SpecialDoc . class ) ;
}
@Test // DATAMONGO-1421
public void addCriteriaForSamePropertyMultipleTimesShouldThrowAndSafelySerializeErrorMessage ( ) {
exception . expect ( InvalidMongoDbApiUsageException . class ) ;
exception . expectMessage ( "second 'value' criteria" ) ;
exception . expectMessage ( "already contains '{ \"value\" : { \"$java\" : VAL_1 } }'" ) ;
assertThatExceptionOfType ( InvalidMongoDbApiUsageException . class ) . isThrownBy ( ( ) - > {
Query query = new Query ( ) ;
query . addCriteria ( where ( "value" ) . is ( EnumType . VAL_1 ) ) ;
query . addCriteria ( where ( "value" ) . is ( EnumType . VAL_2 ) ) ;
} ) . withMessageContaining ( "second 'value' criteria" )
. withMessageContaining ( "already contains '{ \"value\" : { \"$java\" : VAL_1 } }'" ) ;
Query query = new Query ( ) ;
query . addCriteria ( where ( "value" ) . is ( EnumType . VAL_1 ) ) ;
query . addCriteria ( where ( "value" ) . is ( EnumType . VAL_2 ) ) ;
}
enum EnumType {