4444
4545import  java .io .PrintWriter ;
4646import  java .io .StringWriter ;
47- import  java .util .ArrayList ;
4847import  java .util .Arrays ;
4948import  java .util .List ;
5049
@@ -685,24 +684,24 @@ public void queryRestrictions_sortWrongOrderOnInequality_isInvalid() throws Exce
685684  public  void  queryRestrictions_surprisingMultipleValuesAllMustMatch_returnsNoEntities ()
686685      throws  Exception  {
687686    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 );
691688    a .setProperty ("x" , xs );
692689    datastore .put (a );
693690
694691    // [START surprising_behavior_example_1] 
695692    Query  q  =
696693        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 )));
699698    // [END surprising_behavior_example_1] 
700699
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 (); 
706705  }
707706
708707  @ Test 
@@ -716,21 +715,24 @@ public void queryRestrictions_surprisingMultipleValuesEquals_returnsMatchedEntit
716715    c .setProperty ("x" , ImmutableList .<Long >of (-6L , 2L ));
717716    Entity  d  = new  Entity ("Widget" , "d" );
718717    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 ));
720721
721722    // [START surprising_behavior_example_2] 
722723    Query  q  =
723724        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 )));
726729    // [END surprising_behavior_example_2] 
727730
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 
728734    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 ());
734736  }
735737
736738  @ Test 
@@ -752,6 +754,9 @@ public void queryRestrictions_surprisingMultipleValuesNotEquals_returnsMatchedEn
752754    Query  q  = new  Query ("Widget" ).setFilter (new  FilterPredicate ("x" , FilterOperator .NOT_EQUAL , 1 ));
753755    // [END surprising_behavior_example_3] 
754756
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 
755760    List <Entity > results  = datastore .prepare (q ).asList (FetchOptions .Builder .withDefaults ());
756761    assertThat (getKeys (results ))
757762        .named ("query result keys" )
@@ -770,17 +775,21 @@ public void queryRestrictions_surprisingMultipleValuesTwoNotEquals_returnsMatche
770775    // [START surprising_behavior_example_4] 
771776    Query  q  =
772777        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 )));
775782    // [END surprising_behavior_example_4] 
776783
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 
777791    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 ());
784793  }
785794
786795  private  Entity  retrievePersonWithLastName (String  targetLastName ) {
0 commit comments