44
44
45
45
import java .io .PrintWriter ;
46
46
import java .io .StringWriter ;
47
- import java .util .ArrayList ;
48
47
import java .util .Arrays ;
49
48
import java .util .List ;
50
49
@@ -685,24 +684,24 @@ public void queryRestrictions_sortWrongOrderOnInequality_isInvalid() throws Exce
685
684
public void queryRestrictions_surprisingMultipleValuesAllMustMatch_returnsNoEntities ()
686
685
throws Exception {
687
686
Entity a = new Entity ("Widget" , "a" );
688
- ArrayList <Long > xs = new ArrayList <>();
689
- xs .add (1L );
690
- xs .add (2L );
687
+ List <Long > xs = Arrays .asList (1L , 2L );
691
688
a .setProperty ("x" , xs );
692
689
datastore .put (a );
693
690
694
691
// [START surprising_behavior_example_1]
695
692
Query q =
696
693
new Query ("Widget" )
697
- .setFilter (new FilterPredicate ("x" , FilterOperator .GREATER_THAN , 1 ))
698
- .setFilter (new FilterPredicate ("x" , FilterOperator .LESS_THAN , 2 ));
694
+ .setFilter (
695
+ CompositeFilterOperator .and (
696
+ new FilterPredicate ("x" , FilterOperator .GREATER_THAN , 1 ),
697
+ new FilterPredicate ("x" , FilterOperator .LESS_THAN , 2 )));
699
698
// [END surprising_behavior_example_1]
700
699
701
- // Note: The documentation describes that the entity "a" will not match
702
- // because no value matches all filters. When run with the local test
703
- // runner, the entity "a" *is* matched. This may be a difference in
704
- // behavior between the local devserver and Cloud Datastore, so there
705
- // aren't any assertions we can make in this test.
700
+ // Entity "a" will not match because no individual value matches all filters.
701
+ // See the documentation for more details:
702
+ // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways
703
+ List < Entity > results = datastore . prepare ( q ). asList ( FetchOptions . Builder . withDefaults ());
704
+ assertThat ( results ). named ( "query results" ). isEmpty ();
706
705
}
707
706
708
707
@ Test
@@ -716,21 +715,24 @@ public void queryRestrictions_surprisingMultipleValuesEquals_returnsMatchedEntit
716
715
c .setProperty ("x" , ImmutableList .<Long >of (-6L , 2L ));
717
716
Entity d = new Entity ("Widget" , "d" );
718
717
d .setProperty ("x" , ImmutableList .<Long >of (-6L , 4L ));
719
- datastore .put (ImmutableList .<Entity >of (a , b , c , d ));
718
+ Entity e = new Entity ("Widget" , "e" );
719
+ e .setProperty ("x" , ImmutableList .<Long >of (1L , 2L , 3L ));
720
+ datastore .put (ImmutableList .<Entity >of (a , b , c , d , e ));
720
721
721
722
// [START surprising_behavior_example_2]
722
723
Query q =
723
724
new Query ("Widget" )
724
- .setFilter (new FilterPredicate ("x" , FilterOperator .EQUAL , 1 ))
725
- .setFilter (new FilterPredicate ("x" , FilterOperator .EQUAL , 2 ));
725
+ .setFilter (
726
+ CompositeFilterOperator .and (
727
+ new FilterPredicate ("x" , FilterOperator .EQUAL , 1 ),
728
+ new FilterPredicate ("x" , FilterOperator .EQUAL , 2 )));
726
729
// [END surprising_behavior_example_2]
727
730
731
+ // Only "a" and "e" have both 1 and 2 in the "x" array-valued property.
732
+ // See the documentation for more details:
733
+ // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways
728
734
List <Entity > results = datastore .prepare (q ).asList (FetchOptions .Builder .withDefaults ());
729
- assertThat (getKeys (results )).named ("query result keys" ).contains (a .getKey ());
730
-
731
- // Note: When run in the test server, this matches "c" as expected and does
732
- // not match "d" as expected. For some reason it does *not* match "b".
733
- // The behavior of queries on repeated values is definitely surprising.
735
+ assertThat (getKeys (results )).named ("query result keys" ).containsExactly (a .getKey (), e .getKey ());
734
736
}
735
737
736
738
@ Test
@@ -752,6 +754,9 @@ public void queryRestrictions_surprisingMultipleValuesNotEquals_returnsMatchedEn
752
754
Query q = new Query ("Widget" ).setFilter (new FilterPredicate ("x" , FilterOperator .NOT_EQUAL , 1 ));
753
755
// [END surprising_behavior_example_3]
754
756
757
+ // The query matches any entity that has a some value other than 1. Only
758
+ // entity "e" is not matched. See the documentation for more details:
759
+ // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways
755
760
List <Entity > results = datastore .prepare (q ).asList (FetchOptions .Builder .withDefaults ());
756
761
assertThat (getKeys (results ))
757
762
.named ("query result keys" )
@@ -770,17 +775,21 @@ public void queryRestrictions_surprisingMultipleValuesTwoNotEquals_returnsMatche
770
775
// [START surprising_behavior_example_4]
771
776
Query q =
772
777
new Query ("Widget" )
773
- .setFilter (new FilterPredicate ("x" , FilterOperator .NOT_EQUAL , 1 ))
774
- .setFilter (new FilterPredicate ("x" , FilterOperator .NOT_EQUAL , 2 ));
778
+ .setFilter (
779
+ CompositeFilterOperator .and (
780
+ new FilterPredicate ("x" , FilterOperator .NOT_EQUAL , 1 ),
781
+ new FilterPredicate ("x" , FilterOperator .NOT_EQUAL , 2 )));
775
782
// [END surprising_behavior_example_4]
776
783
784
+ // The two NOT_EQUAL filters in the query become like the combination of queries:
785
+ // x < 1 OR (x > 1 AND x < 2) OR x > 2
786
+ //
787
+ // Only "b" has some value which matches the "x > 2" portion of this query.
788
+ //
789
+ // See the documentation for more details:
790
+ // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways
777
791
List <Entity > results = datastore .prepare (q ).asList (FetchOptions .Builder .withDefaults ());
778
- assertThat (getKeys (results )).named ("query result keys" ).contains (b .getKey ());
779
-
780
- // Note: The documentation describes that the entity "a" will not match.
781
- // When run with the local test runner, the entity "a" *is* matched. This
782
- // may be a difference in behavior between the local devserver and Cloud
783
- // Datastore.
792
+ assertThat (getKeys (results )).named ("query result keys" ).containsExactly (b .getKey ());
784
793
}
785
794
786
795
private Entity retrievePersonWithLastName (String targetLastName ) {
0 commit comments