You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/03/15 01:27:27 UTC

[39/50] [abbrv] git commit: Adding 43 more legacy tests for query-index for total of 100 (7 are still failing).

Adding 43 more legacy tests for query-index for total of 100 (7 are still failing).


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/c801a47e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/c801a47e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/c801a47e

Branch: refs/heads/asyncqueue
Commit: c801a47efdf5e8a02204a0dc37fa8c8832001993
Parents: e89b343
Author: Dave Johnson <dm...@apigee.com>
Authored: Mon Mar 10 10:45:55 2014 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Mon Mar 10 10:45:55 2014 -0400

----------------------------------------------------------------------
 .../persistence/index/impl/EsProvider.java      |   62 +-
 .../usergrid/persistence/query/Query.java       |    2 +
 .../persistence/index/impl/CollectionIT.java    |   17 +
 .../impl/EntityCollectionIndexStressTest.java   |    2 +-
 .../index/impl/EntityCollectionIndexTest.java   |    6 +
 .../usergrid/persistence/index/impl/GeoIT.java  |   21 +-
 .../persistence/index/impl/IndexIT.java         |    7 +
 .../index/legacy/EntityManagerFacade.java       |    3 +
 .../query/AbstractIteratingQueryIT.java         | 1385 ++++++++++++++++++
 .../persistence/query/AllInCollectionIT.java    |   33 +
 .../persistence/query/AllInConnectionIT.java    |   32 +
 .../query/AllInConnectionNoTypeIT.java          |   55 +
 .../query/IntersectionUnionPagingIT.java        |  168 +++
 .../query/MultiOrderByCollectionIT.java         |   33 +
 .../MultiOrderByComplexUnionCollectionIT.java   |   33 +
 .../MultiOrderByComplexUnionConnectionIT.java   |   33 +
 .../query/MultiOrderByConnectionIT.java         |   34 +
 .../query/NotOrderByCollectionIT.java           |   33 +
 .../query/NotOrderByConnectionIT.java           |   33 +
 ...gleOrderByBoundRangeScanAscCollectionIT.java |   33 +
 ...gleOrderByBoundRangeScanAscConnectionIT.java |   33 +
 ...leOrderByBoundRangeScanDescCollectionIT.java |   33 +
 ...leOrderByBoundRangeScanDescConnectionIT.java |   33 +
 ...eOrderByComplexIntersectionCollectionIT.java |   33 +
 ...eOrderByComplexIntersectionConnectionIT.java |   34 +
 .../SingleOrderByComplexUnionCollectionIT.java  |   33 +
 .../SingleOrderByComplexUnionConnectionIT.java  |   33 +
 .../SingleOrderByIntersectionCollectionIT.java  |   33 +
 .../SingleOrderByIntersectionConnectionIT.java  |   33 +
 .../SingleOrderByLessThanLimitCollectionIT.java |   33 +
 .../SingleOrderByLessThanLimitConnectionIT.java |   33 +
 .../SingleOrderByMaxLimitCollectionIT.java      |   34 +
 .../SingleOrderByMaxLimitConnectionIT.java      |   34 +
 ...SingleOrderByNoIntersectionCollectionIT.java |   33 +
 ...SingleOrderByNoIntersectionConnectionIT.java |   33 +
 .../query/SingleOrderByNotCollectionIT.java     |   33 +
 .../query/SingleOrderByNotConnectionIT.java     |   33 +
 ...OrderBySameRangeScanGreaterCollectionIT.java |   33 +
 ...OrderBySameRangeScanGreaterConnectionIT.java |   33 +
 ...meRangeScanGreaterThanEqualCollectionIT.java |   33 +
 ...gleOrderBySameRangeScanLessCollectionIT.java |   33 +
 ...gleOrderBySameRangeScanLessConnectionIT.java |   33 +
 ...ySameRangeScanLessThanEqualCollectionIT.java |   33 +
 ...ySameRangeScanLessThanEqualConnectionIT.java |   33 +
 .../src/test/resources/usergrid-UNIT.properties |    1 -
 45 files changed, 2787 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsProvider.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsProvider.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsProvider.java
index edae017..5e5ba44 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsProvider.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsProvider.java
@@ -41,7 +41,7 @@ public class EsProvider {
     private static final Logger log = LoggerFactory.getLogger( EsProvider.class ); 
 
     private final IndexFig indexFig;
-    private Client client;
+    private static Client client;
 
     @Inject
     public EsProvider( IndexFig fig ) {
@@ -57,41 +57,45 @@ public class EsProvider {
 
     public static synchronized Client getClient( IndexFig fig ) {
 
-        Client newClient = null;
+        if ( client == null ) {
 
-        if ( fig.isEmbedded() ) {
+            Client newClient = null;
 
-            log.info("--------------------------------");
-            log.info("Starting embedded ElasticSearch");
-            log.info("--------------------------------");
+            if ( fig.isEmbedded() ) {
 
-            int port = AvailablePortFinder.getNextAvailable( 2000 );
-            Settings settings = ImmutableSettings.settingsBuilder()
-                    .put( "node.http.enabled", true )
-                    .put( "transport.tcp.port", port )
-                    .put( "path.logs", "target/elasticsearch/logs_" + port )
-                    .put( "path.data", "target/elasticsearch/data_" + port )
-                    .put( "gateway.type", "none" )
-                    .put( "index.store.type", "memory" )
-                    .put( "index.number_of_shards", 1 )
-                    .put( "index.number_of_replicas", 1 ).build();
+                log.info("--------------------------------");
+                log.info("Starting embedded ElasticSearch");
+                log.info("--------------------------------");
 
-            Node node = NodeBuilder.nodeBuilder().local( true ).settings( settings ).node();
-            newClient = node.client();
-        
-        } else { // build client that connects to all hosts
+                int port = AvailablePortFinder.getNextAvailable( 2000 );
+                Settings settings = ImmutableSettings.settingsBuilder()
+                        .put( "node.http.enabled", true )
+                        .put( "transport.tcp.port", port )
+                        .put( "path.logs", "target/elasticsearch/logs_" + port )
+                        .put( "path.data", "target/elasticsearch/data_" + port )
+                        .put( "gateway.type", "none" )
+                        .put( "index.store.type", "memory" )
+                        .put( "index.number_of_shards", 1 )
+                        .put( "index.number_of_replicas", 1 ).build();
 
-            log.info("--------------------------------");
-            log.info("Creating ElasticSearch client");
-            log.info("--------------------------------");
+                Node node = NodeBuilder.nodeBuilder().local( true ).settings( settings ).node();
+                newClient = node.client();
+            
+            } else { // build client that connects to all hosts
 
-            TransportClient transportClient = new TransportClient();
-            for ( String host : fig.getHosts().split(",") ) {
-                transportClient.addTransportAddress(
-                        new InetSocketTransportAddress( host, fig.getPort() ));
+                log.info("--------------------------------");
+                log.info("Creating ElasticSearch client");
+                log.info("--------------------------------");
+
+                TransportClient transportClient = new TransportClient();
+                for ( String host : fig.getHosts().split(",") ) {
+                    transportClient.addTransportAddress(
+                            new InetSocketTransportAddress( host, fig.getPort() ));
+                }
+                newClient = transportClient;
             }
-            newClient = transportClient;
+            client = newClient;
         }
-        return newClient;
+        return client;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/query/Query.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/query/Query.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/query/Query.java
index c81bc85..1feb56a 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/query/Query.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/query/Query.java
@@ -75,6 +75,8 @@ import org.slf4j.LoggerFactory;
 public class Query {
     private static final Logger logger = LoggerFactory.getLogger( Query.class );
 
+    public static final int PAGE_SIZE = 1000;
+
     public static final int DEFAULT_LIMIT = 10;
     public static final int MAX_LIMIT = 1000;
     public static final String PROPERTY_Id = "uuid";

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/CollectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/CollectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/CollectionIT.java
index 8589452..9feeaf6 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/CollectionIT.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/CollectionIT.java
@@ -54,6 +54,7 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import org.junit.Before;
 import org.junit.ClassRule;
+import org.junit.Ignore;
 import org.junit.runner.RunWith;
 
 
@@ -157,6 +158,8 @@ public class CollectionIT {
         activity3 = app.get( activity3.getId() );
         app.addToCollection( user, "activities", activity3 );
 
+        em.refreshIndex();
+
         // empty query
         Query query = new Query();
         Results r = app.searchCollection( user, "activities", query );
@@ -238,6 +241,8 @@ public class CollectionIT {
         Entity user = em.create( "user", properties );
         assertNotNull( user );
 
+        em.refreshIndex();
+
         // EntityRef
         Query query = new Query();
         query.addEqualityFilter( "firstname", firstName );
@@ -257,6 +262,8 @@ public class CollectionIT {
 
         em.update( user );
 
+        em.refreshIndex();
+
         // search with the old username, should be no results
         query = new Query();
         query.addEqualityFilter( "firstname", firstName );
@@ -293,6 +300,8 @@ public class CollectionIT {
         Entity user = em.create( "user", properties );
         assertNotNull( user );
 
+        em.refreshIndex();
+
         // EntityRef
         Query query = new Query();
         query.addEqualityFilter( "middlename", middleName );
@@ -320,6 +329,8 @@ public class CollectionIT {
         Entity user = em.create( "user", properties );
         assertNotNull( user );
 
+        em.refreshIndex();
+
         // EntityRef
         Query query = new Query();
         query.addEqualityFilter( "lastname", lastName );
@@ -391,6 +402,8 @@ public class CollectionIT {
         Entity group = em.create( "group", properties );
         assertNotNull( group );
 
+        em.refreshIndex();
+
         // EntityRef
         Query query = new Query();
         query.addEqualityFilter( "name", groupName );
@@ -419,6 +432,8 @@ public class CollectionIT {
         Entity group = em.create( "group", properties );
         assertNotNull( group );
 
+        em.refreshIndex();
+
         // EntityRef
         Query query = new Query();
         query.addEqualityFilter( "title", titleName );
@@ -471,6 +486,8 @@ public class CollectionIT {
 
         em.addToCollection( user, "activities", em.create( "activity", properties ) );
 
+        em.refreshIndex();
+
         Results r = em.searchCollection( user, "activities", Query.searchForProperty( "verb", "post" ) );
         LOG.info( JsonUtils.mapToFormattedJsonString( r.getEntities() ) );
         assertEquals( 2, r.size() );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexStressTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexStressTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexStressTest.java
index 62cf7da..605c44c 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexStressTest.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexStressTest.java
@@ -74,7 +74,7 @@ public class EntityCollectionIndexStressTest {
         Id orgId = new SimpleId("organization");
         CollectionScope scope = new CollectionScopeImpl( appId, orgId, "characters" );
 
-        int limit = 10000;
+        int limit = 2000;
         StopWatch timer = new StopWatch();
         timer.start();
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
index b4e247e..18f5ac4 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
@@ -111,6 +111,8 @@ public class EntityCollectionIndexTest {
         log.info( "Total time to index {} entries {}ms, average {}ms/entry", 
             count, timer.getTime(), timer.getTime() / count );
 
+        entityIndex.refresh();
+
         testQueries( entityIndex );
     }
 
@@ -136,12 +138,16 @@ public class EntityCollectionIndexTest {
         entity = entityManager.write( entity ).toBlockingObservable().last();
         entityIndex.index( entity );
 
+        entityIndex.refresh();
+
         Results results = entityIndex.execute( Query.fromQL( "name contains 'Ferrari*'"));
         assertEquals( 1, results.getEntities().size() );
 
         entityManager.delete( entity.getId() );
         entityIndex.deindex( entity );
 
+        entityIndex.refresh();
+
         results = entityIndex.execute( Query.fromQL( "name contains 'Ferrari*'"));
         assertEquals( 0, results.getEntities().size() );
     }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/GeoIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/GeoIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/GeoIT.java
index dafa389..054dadd 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/GeoIT.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/GeoIT.java
@@ -118,6 +118,8 @@ public class GeoIT {
         assertNotNull( user );
 		LOG.info( user.toString() );
 
+        em.refreshIndex();
+
 		// Folsom and 7th more than 100 meters from Folson and Bryant
 		Query q = Query.fromQL("location within 100 of " 
 			+ folsomAnd7th.getLat() + "," + folsomAnd7th.getLon() + " limit 100");
@@ -134,6 +136,8 @@ public class GeoIT {
         updatePos( em, new SimpleEntityRef( user.getId(), user.getVersion() ), 
 			paloalto.getLat(), paloalto.getLon() );
 
+        em.refreshIndex();
+
 		// user no longer within 200m of that San Francico intersection  
 		q = Query.fromQL("location within 200 of " + folsomAndBryant.getLat() 
 				+ "," + folsomAndBryant.getLon() + " limit 100");
@@ -143,6 +147,8 @@ public class GeoIT {
 		// move user to the other SF intersection
         updatePos( em, user, folsomAnd7th.getLat(), folsomAnd7th.getLon() );
 
+        em.refreshIndex();
+
 		// now they are close to Folsom and Bryant
 		q = Query.fromQL("location within 1000 of " 
 				+ folsomAndBryant.getLat() + "," + folsomAndBryant.getLon() + " limit 100");
@@ -167,6 +173,8 @@ public class GeoIT {
         Entity user2 = em.create( "user", properties2 );
         assertNotNull( user2 );
         
+        em.refreshIndex();
+
 		q = Query.fromQL("location within 10000 of " 
 				+ folsomAndBryant.getLat() + "," + folsomAndBryant.getLon() + " limit 100");
 		results = em.searchCollection(null, "users", q);
@@ -216,6 +224,8 @@ public class GeoIT {
         Entity restaurant = em.create( "restaurant", properties );
         assertNotNull( restaurant );
 
+        em.refreshIndex();
+
 		// TODO: update with new Core Persistence graph API
 
 //        em.createConnection( user, "likes", restaurant );
@@ -266,6 +276,8 @@ public class GeoIT {
             em.create( "dog", data );
         }
 
+        em.refreshIndex();
+
         // earth's circumference is 40075km; up it to 50000km, to be safe
         Query query = new Query();
         query.addFilter( "location within 50000000 of -90, -180" );
@@ -291,7 +303,6 @@ public class GeoIT {
     }
 
 
-    @Ignore
     @Test
     public void testSamePointPaging() throws Exception {
 
@@ -314,6 +325,8 @@ public class GeoIT {
             em.create( "store", data );
         }
 
+        em.refreshIndex();
+
         Query query = new Query();
         // earth's circumference is 40,075 kilometers. Up it to 50,000kilometers
         // just to be save
@@ -339,7 +352,6 @@ public class GeoIT {
     }
 
     
-    @Ignore
     @Test
     public void testDistanceByLimit() throws Exception {
 
@@ -378,6 +390,8 @@ public class GeoIT {
             em.create( "car", data );
         }
 
+        em.refreshIndex();
+
         // earth's circumference is 40075km; up it to 50,000km, just to be safe.
         Query query = new Query();
         query.addFilter( "location within " + (50000 * 1000) + " of -90, -180" );
@@ -399,7 +413,6 @@ public class GeoIT {
     }
 
 
-    @Ignore
     @Test
     public void testGeoWithIntersection() throws Exception {
 
@@ -429,6 +442,8 @@ public class GeoIT {
             created.add( e );
         }
 
+        em.refreshIndex();
+
         int startDelta = size - min;
 
         //    String queryString = String.format("select * where location within 100 of 0,

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/IndexIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/IndexIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/IndexIT.java
index 674aa3a..fc0af93 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/IndexIT.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/IndexIT.java
@@ -40,6 +40,7 @@ import org.jukito.JukitoRunner;
 import org.jukito.UseModules;
 import static org.junit.Assert.assertEquals;
 import org.junit.ClassRule;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -96,6 +97,8 @@ public class IndexIT {
 
             em.create( "item", properties );
         }
+        
+        em.refreshIndex();
 
         int i = 0;
         
@@ -165,6 +168,8 @@ public class IndexIT {
             em.create( "item", properties );
         }
 
+        em.refreshIndex();
+
         Query query = Query.fromQL( "name < 'Delta' order by name" );
         Results r = em.searchCollection( em.getApplicationRef(), "items", query );
         LOG.info( JsonUtils.mapToFormattedJsonString( r.getEntities() ) );
@@ -288,6 +293,8 @@ public class IndexIT {
             em.create( "item", properties );
         }
 
+        em.refreshIndex();
+
         Query query = Query.fromQL( "group = 1 order by name desc" );
         Results r = em.searchCollection( em.getApplicationRef(), "items", query );
         LOG.info( JsonUtils.mapToFormattedJsonString( r.getEntities() ) );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
index fa341bc..e8eb5e1 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
@@ -30,6 +30,7 @@ import org.apache.usergrid.persistence.model.entity.Entity;
 import org.apache.usergrid.persistence.model.entity.Id;
 import org.apache.usergrid.persistence.model.entity.SimpleId;
 import org.apache.usergrid.persistence.model.field.LocationField;
+import org.apache.usergrid.persistence.model.field.LongField;
 import org.apache.usergrid.persistence.model.field.value.Location;
 import org.apache.usergrid.persistence.model.util.UUIDGenerator;
 import org.apache.usergrid.persistence.query.EntityRef;
@@ -101,6 +102,8 @@ public class EntityManagerFacade {
 
         Entity entity = new Entity(new SimpleId(UUIDGenerator.newTimeUUID(), type ));
         entity = EntityBuilder.fromMap( scope.getName(), entity, properties );
+        entity.setField(new LongField("created", entity.getId().getUuid().timestamp()) );
+        entity.setField(new LongField("modified", entity.getId().getUuid().timestamp()) );
         entity = ecm.write( entity ).toBlockingObservable().last();
 
         eci.index( entity );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AbstractIteratingQueryIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AbstractIteratingQueryIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AbstractIteratingQueryIT.java
new file mode 100644
index 0000000..8aefd2e
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AbstractIteratingQueryIT.java
@@ -0,0 +1,1385 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import com.google.inject.Inject;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.usergrid.persistence.collection.EntityCollectionManagerFactory;
+import org.apache.usergrid.persistence.collection.cassandra.CassandraRule;
+import org.apache.usergrid.persistence.collection.guice.MigrationManagerRule;
+import org.apache.usergrid.persistence.index.EntityCollectionIndexFactory;
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.apache.usergrid.persistence.index.legacy.CoreApplication;
+import org.apache.usergrid.persistence.index.legacy.CoreITSetup;
+import org.apache.usergrid.persistence.index.legacy.CoreITSetupImpl;
+import org.apache.usergrid.persistence.index.legacy.EntityManagerFacade;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.entity.SimpleId;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public abstract class AbstractIteratingQueryIT {
+    private static final Logger LOG = LoggerFactory.getLogger( AbstractIteratingQueryIT.class );
+
+    @ClassRule
+    public static CassandraRule cass = new CassandraRule();
+
+    @Inject
+    @Rule
+    public MigrationManagerRule migrationManagerRule;
+    
+    @ClassRule
+    public static CoreITSetup setup = new CoreITSetupImpl();
+
+    @Rule
+    public CoreApplication app = new CoreApplication( setup );
+
+    @Inject
+    public EntityCollectionManagerFactory cmf;
+    
+    @Inject
+    public EntityCollectionIndexFactory cif;
+
+    private EntityManagerFacade em;
+
+    @Before
+    public void setup() {
+        Id appId = new SimpleId("application");
+        Id orgId = new SimpleId("organization");
+
+        em = new EntityManagerFacade( orgId, appId, cmf, cif );
+
+        app.setEntityManager( em );                
+    }
+
+
+    public void singleOrderByMaxLimit( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = Query.MAX_LIMIT;
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+            entity.put( "name", String.valueOf( i ) );
+
+            io.writeEntity( entity );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "created" );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( String.valueOf( count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( size, count );
+    }
+
+
+    protected void singleOrderByIntersection( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 700;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+        int intersectIncrement = 5;
+
+        long start = System.currentTimeMillis();
+
+        List<String> expected = new ArrayList<String>( size / intersectIncrement );
+
+        LOG.info( "Writing {} entities.", size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            String name = String.valueOf( i );
+
+            boolean intersect = i % intersectIncrement == 0;
+
+            entity.put( "name", String.valueOf( i ) );
+            // if we hit the increment, set this to true
+            entity.put( "intersect", intersect );
+
+            io.writeEntity( entity );
+
+            if ( intersect ) {
+                expected.add( name );
+            }
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "created" );
+        query.addEqualityFilter( "intersect", true );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( expected.size(), count );
+    }
+
+
+    protected void singleOrderByComplexIntersection( IoHelper io ) throws Exception {
+
+        int size = 5000;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+        int intersectIncrement = 5;
+        int secondIncrement = 9;
+
+        long start = System.currentTimeMillis();
+
+        io.doSetup();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expectedResults = new ArrayList<String>( size / secondIncrement );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            String name = String.valueOf( i );
+            boolean intersect1 = i % intersectIncrement == 0;
+            boolean intersect2 = i % secondIncrement == 0;
+            entity.put( "name", name );
+            // if we hit the increment, set this to true
+
+            entity.put( "intersect", intersect1 );
+            entity.put( "intersect2", intersect2 );
+            io.writeEntity( entity );
+
+            if ( intersect1 && intersect2 ) {
+                expectedResults.add( name );
+            }
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "created" );
+        query.addEqualityFilter( "intersect", true );
+        query.addEqualityFilter( "intersect2", true );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expectedResults.get( count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( expectedResults.size(), count );
+    }
+
+
+    protected void singleOrderByNoIntersection( IoHelper io ) throws Exception {
+        io.doSetup();
+
+        int size = 2000;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+        int secondIncrement = 9;
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+            entity.put( "name", String.valueOf( i ) );
+            // if we hit the increment, set this to true
+            entity.put( "intersect", false );
+            entity.put( "intersect2", i % secondIncrement == 0 );
+            io.writeEntity( entity );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "created" );
+        // nothing will ever match this, the search should short circuit
+        query.addEqualityFilter( "intersect", true );
+        query.addEqualityFilter( "intersect2", true );
+        query.setLimit( queryLimit );
+
+        start = System.currentTimeMillis();
+
+        Results results = io.getResults( query );
+
+        // now do simple ordering, should be returned in order
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, 0 );
+
+        assertEquals( 0, results.size() );
+    }
+
+
+    protected void singleOrderByComplexUnion( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 2000;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+        int intersectIncrement = 5;
+        int secondIncrement = 9;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expectedResults = new ArrayList<String>( size / secondIncrement );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            String name = String.valueOf( i );
+            boolean intersect1 = i % intersectIncrement == 0;
+            boolean intersect2 = i % secondIncrement == 0;
+            entity.put( "name", name );
+            // if we hit the increment, set this to true
+
+            entity.put( "intersect", intersect1 );
+            entity.put( "intersect2", intersect2 );
+            io.writeEntity( entity );
+
+            if ( intersect1 || intersect2 ) {
+                expectedResults.add( name );
+            }
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = Query.fromQL( "select * where intersect = true OR intersect2 = true order by created" );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expectedResults.get( count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( expectedResults.size(), count );
+    }
+
+
+    protected void singleOrderByNot( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 2000;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+        int intersectIncrement = 5;
+        int secondIncrement = 9;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expectedResults = new ArrayList<String>( size / secondIncrement );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            String name = String.valueOf( i );
+            boolean intersect1 = i % intersectIncrement == 0;
+            boolean intersect2 = i % secondIncrement == 0;
+            entity.put( "name", name );
+            // if we hit the increment, set this to true
+
+            entity.put( "intersect", intersect1 );
+            entity.put( "intersect2", intersect2 );
+            io.writeEntity( entity );
+
+            if ( !( intersect1 && intersect2 ) ) {
+                expectedResults.add( name );
+            }
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = Query.fromQL( "select * where NOT (intersect = true AND intersect2 = true) order by created" );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expectedResults.get( count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( expectedResults.size(), count );
+    }
+
+
+    public void singleOrderByLessThanLimit( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = Query.MAX_LIMIT;
+
+        int matchMax = queryLimit - 1;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( matchMax );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+            boolean searched = i < matchMax;
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "searched", searched );
+            io.writeEntity( entity );
+
+            if ( searched ) {
+                expected.add( name );
+            }
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "created" );
+        query.setLimit( queryLimit );
+        query.addEqualityFilter( "searched", true );
+
+        int count = 0;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results = io.getResults( query );
+
+        for ( int i = 0; i < results.size(); i++ ) {
+            assertEquals( expected.get( count ), results.getEntities().get( i ).getField("name").getValue() );
+            count++;
+        }
+
+        assertTrue( results.getCursor() == null );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( expected.size(), count );
+    }
+
+
+    public void singleOrderBySameRangeScanLessThanEqual( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = 100;
+        int startValue = 400;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "index", i );
+            io.writeEntity( entity );
+            expected.add( name );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "index desc" );
+        query.addLessThanEqualFilter( "index", startValue );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+        int delta = size - startValue;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results;
+
+        do {
+
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( size - delta - count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.hasCursor() );
+
+        assertEquals( expected.size() - delta + 1, count );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+    }
+
+
+    public void singleOrderBySameRangeScanLessEqual( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = 100;
+        int startValue = 400;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "index", i );
+            io.writeEntity( entity );
+            expected.add( name );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "index desc" );
+        query.addLessThanFilter( "index", startValue );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+        int delta = size - startValue;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results;
+
+        do {
+
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( size - delta - count - 1 ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.hasCursor() );
+
+        assertEquals( expected.size() - delta, count );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+    }
+
+
+    public void singleOrderBySameRangeScanGreaterThanEqual( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = 100;
+        int startValue = 100;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "index", i );
+            io.writeEntity( entity );
+            expected.add( name );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "index desc" );
+        query.addGreaterThanEqualFilter( "index", startValue );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results;
+
+        do {
+
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( size - count - 1 ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.hasCursor() );
+
+        assertEquals( expected.size() - startValue, count );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+    }
+
+
+    public void singleOrderBySameRangeScanGreater( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = 100;
+        int startValue = 99;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "index", i );
+            io.writeEntity( entity );
+            expected.add( name );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.addSort( "index desc" );
+        query.addGreaterThanFilter( "index", startValue );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results;
+
+        do {
+
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( size - count - 1 ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.hasCursor() );
+
+        assertEquals( expected.size() - startValue - 1, count );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+    }
+
+
+    public void singleOrderByBoundRangeScanDesc( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = 100;
+        int startValue = 100;
+        int endValue = 400;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "index", i );
+            io.writeEntity( entity );
+            expected.add( name );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = Query.fromQL(
+                String.format( "select * where index >= %d AND index <= %d order by index desc", startValue,
+                        endValue ) );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+        int delta = size - endValue;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results;
+
+        do {
+
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( size - count - delta ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.hasCursor() );
+
+        assertEquals( expected.size() - startValue - delta + 1, count );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+    }
+
+
+    public void singleOrderByBoundRangeScanAsc( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 500;
+        int queryLimit = 100;
+        int startValue = 100;
+        int endValue = 400;
+
+        long start = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writing {} entities.", size );
+
+        List<String> expected = new ArrayList<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            String name = String.valueOf( i );
+
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            entity.put( "name", name );
+            entity.put( "index", i );
+            io.writeEntity( entity );
+            expected.add( name );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = Query.fromQL(
+                String.format( "select * where index >= %d AND index <= %d order by index asc", startValue,
+                        endValue ) );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+        int delta = size - endValue;
+
+        start = System.currentTimeMillis();
+
+        // now do simple ordering, should be returned in order
+        Results results;
+
+        do {
+
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( expected.get( delta + count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.hasCursor() );
+
+        assertEquals( expected.size() - startValue - delta + 1, count );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+    }
+
+
+    /**
+     * Tests that when an empty query is issued, we page through all entities correctly
+     *
+     * @param io the io helper
+     */
+    public void allIn( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 300;
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+            entity.put( "name", String.valueOf( i ) );
+
+            io.writeEntity( entity );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = new Query();
+        query.setLimit( 100 );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                assertEquals( String.valueOf( count ), results.getEntities().get( i ).getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( size, count );
+    }
+
+
+    protected void multiOrderBy( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 2000;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+
+        Set<Entity> sortedResults = new TreeSet<Entity>( new Comparator<Entity>() {
+
+            @Override
+            public int compare( Entity o1, Entity o2 ) {
+                boolean o1Boolean = ( Boolean ) o1.getField( "boolean" ).getValue();
+                boolean o2Boolean = ( Boolean ) o2.getField( "boolean" ).getValue();
+
+                if ( o1Boolean != o2Boolean ) {
+                    if ( o1Boolean ) {
+                        return -1;
+                    }
+
+                    return 1;
+                }
+
+                int o1Index = ( Integer ) o1.getField( "index" ).getValue();
+                int o2Index = ( Integer ) o2.getField( "index" ).getValue();
+
+                if ( o1Index > o2Index ) {
+                    return 1;
+                }
+                else if ( o2Index > o1Index ) {
+                    return -1;
+                }
+
+                return 0;
+            }
+        } );
+
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            String name = String.valueOf( i );
+            boolean bool = i % 2 == 0;
+            entity.put( "name", name );
+            entity.put( "boolean", bool );
+
+            /**
+             * we want them to be ordered from the "newest" time uuid to the oldec since we
+             * have a low cardinality value as the first second clause.  This way the test
+             *won't accidentally pass b/c the UUID ordering matches the index ordering.  If we were
+             *to reverse the value of index (size-i) the test would pass incorrectly
+             */
+
+            entity.put( "index", i );
+
+            Entity saved = io.writeEntity( entity );
+
+            sortedResults.add( saved );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = Query.fromQL( "select * order by boolean desc, index asc" );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        Iterator<Entity> itr = sortedResults.iterator();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                Entity expected = itr.next();
+                Entity returned = results.getEntities().get( i );
+
+                assertEquals( "Order incorrect", expected.getField("name").getValue(), returned.getField("name").getValue() );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( sortedResults.size(), count );
+    }
+
+
+    protected void multiOrderByComplexUnion( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        int size = 2000;
+        int queryLimit = Query.MAX_LIMIT;
+
+        // the number of entities that should be written including an intersection
+        int intersectIncrement = 5;
+        int secondIncrement = 9;
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        Set<Entity> sortedResults = new TreeSet<Entity>( new Comparator<Entity>() {
+
+            @Override
+            public int compare( Entity o1, Entity o2 ) {
+                long o1Index = ( Long ) o1.getField( "created" ).getValue();
+                long o2Index = ( Long ) o2.getField( "created" ).getValue();
+
+                if ( o1Index > o2Index ) {
+                    return 1;
+                }
+                else if ( o2Index > o1Index ) {
+                    return -1;
+                }
+
+
+                boolean o1Boolean = ( Boolean ) o1.getField( "intersect" ).getValue();
+                boolean o2Boolean = ( Boolean ) o2.getField( "intersect" ).getValue();
+
+                if ( o1Boolean != o2Boolean ) {
+                    if ( o1Boolean ) {
+                        return -1;
+                    }
+
+                    return 1;
+                }
+
+
+                return 0;
+            }
+        } );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+
+            String name = String.valueOf( i );
+            boolean intersect1 = i % intersectIncrement == 0;
+            boolean intersect2 = i % secondIncrement == 0;
+            entity.put( "name", name );
+            // if we hit the increment, set this to true
+
+            entity.put( "intersect", intersect1 );
+            entity.put( "intersect2", intersect2 );
+            Entity e = io.writeEntity( entity );
+
+            if ( intersect1 || intersect2 ) {
+                sortedResults.add( e );
+            }
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query =
+                Query.fromQL( "select * where intersect = true OR intersect2 = true order by created, intersect desc" );
+        query.setLimit( queryLimit );
+
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        Iterator<Entity> expected = sortedResults.iterator();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( Entity result : results.getEntities() ) {
+                assertEquals( expected.next(), result );
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( sortedResults.size(), count );
+    }
+
+
+    /**
+     * Tests that when an empty query is issued, we page through all entities correctly
+     *
+     * @param io the io helper
+     */
+    public void notOrderBy( IoHelper io ) throws Exception {
+
+        io.doSetup();
+
+        /**
+         * Leave this as a large size.  We have to write over 1k to reproduce this issue
+         */
+        int size = 3000;
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+            entity.put( "name", String.valueOf( i ) );
+            entity.put( "boolean", !(i % 100 == 0));
+            entity.put( "index", i);
+
+            io.writeEntity( entity );
+        }
+
+        long stop = System.currentTimeMillis();
+
+        em.refreshIndex();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        Query query = Query.fromQL("select * where NOT boolean = false order by index asc");
+        query.setLimit( 20 );
+
+        int index = 0;
+        int count = 0;
+
+        Results results;
+
+        start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+//                assertEquals( String.valueOf( index ), results.getEntities().get( i ).getName() );
+//                index +=2;
+                count++;
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        stop = System.currentTimeMillis();
+        LOG.info( "Query took {} ms to return {} entities", stop - start, count );
+
+        assertEquals( size/2, count );
+    }
+
+
+    /**
+     * Interface to abstract actually doing I/O targets. The same test logic can be applied to both collections and
+     * connections
+     */
+    public static interface IoHelper {
+        /** Perform any setup required */
+        public void doSetup() throws Exception;
+
+        /**
+         * Write the entity to the data store
+         *
+         * @param entity the entity
+         */
+        public Entity writeEntity( Map<String, Object> entity ) throws Exception;
+
+        /**
+         * Get the results for the query
+         *
+         * @param query the query to get results for
+         *
+         * @return the results of the query
+         */
+        public Results getResults( Query query ) throws Exception;
+    }
+
+
+    public static  class CollectionIoHelper implements IoHelper {
+
+        protected final CoreApplication app;
+
+
+        public CollectionIoHelper( final CoreApplication app ) {
+            this.app = app;
+        }
+
+
+        @Override
+        public void doSetup() throws Exception {
+        }
+
+
+        @Override
+        public Entity writeEntity( Map<String, Object> entity ) throws Exception {
+            return app.getEm().create( "test", entity );
+        }
+
+
+        @Override
+        public Results getResults( Query query ) throws Exception {
+            return app.getEm().searchCollection( app.getEm().getApplicationRef(), "tests", query );
+        }
+    }
+
+
+    public static class ConnectionHelper extends CollectionIoHelper {
+
+        /**
+         *
+         */
+        protected static final String CONNECTION = "connection";
+        protected Entity rootEntity;
+
+
+        public ConnectionHelper( final CoreApplication app) {
+            super( app );
+        }
+
+
+        @Override
+        public void doSetup() throws Exception {
+            Map<String, Object> data = new HashMap<String, Object>();
+            data.put( "name", "rootentity" );
+            rootEntity = app.getEm().create( "root", data );
+        }
+
+
+//        @Override
+//        public Entity writeEntity( Map<String, Object> entity ) throws Exception {
+//            // write to the collection
+//            Entity created = super.writeEntity( entity );
+//            app.getEm().createConnection( rootEntity, CONNECTION, created );
+//
+//            return created;
+//        }
+
+
+//        /*
+//         * (non-Javadoc)
+//         *
+//         * @see
+//         * org.apache.usergrid.persistence.query.SingleOrderByMaxLimitCollection.CollectionIoHelper#
+//         * getResults(org.apache.usergrid.persistence.Query)
+//         */
+//        @Override
+//        public Results getResults( Query query ) throws Exception {
+//            query.setConnectionType( CONNECTION );
+//            query.setEntityType( "test" );
+//            return app.getEm().searchConnectedEntities( rootEntity, query );
+//        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInCollectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInCollectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInCollectionIT.java
new file mode 100644
index 0000000..c476ffb
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInCollectionIT.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class AllInCollectionIT extends AbstractIteratingQueryIT {
+    @Test
+    public void allInCollection() throws Exception {
+        allIn( new CollectionIoHelper( app ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionIT.java
new file mode 100644
index 0000000..f92c4b1
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionIT.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class AllInConnectionIT extends AbstractIteratingQueryIT {
+    @Test
+    public void allInConnection() throws Exception {
+        allIn( new ConnectionHelper(app) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionNoTypeIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionNoTypeIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionNoTypeIT.java
new file mode 100644
index 0000000..8f0286f
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/AllInConnectionNoTypeIT.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.legacy.CoreApplication;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+@Ignore  // no support for connections yet
+public class AllInConnectionNoTypeIT extends AbstractIteratingQueryIT {
+
+    @Test
+    public void allInConnectionNoType() throws Exception {
+        allIn( new ConnectionNoTypeHelper(app) );
+    }
+
+
+    class ConnectionNoTypeHelper extends ConnectionHelper {
+
+        public ConnectionNoTypeHelper( final CoreApplication app ) {
+            super( app );
+        }
+
+
+        /*
+                 * (non-Javadoc)
+                 *
+                 * @see
+                 * org.apache.usergrid.persistence.query.SingleOrderByMaxLimitCollection.ConnectionHelper#getResults
+                 * (org.apache.usergrid.persistence.Query)
+                 */
+        @Override
+        public Results getResults( Query query ) throws Exception {
+            query.setConnectionType( CONNECTION );
+            // don't set it on purpose
+            query.setEntityType( null );
+            return null; // app.getEm().searchConnectedEntities( rootEntity, query );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/IntersectionUnionPagingIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/IntersectionUnionPagingIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/IntersectionUnionPagingIT.java
new file mode 100644
index 0000000..870946b
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/IntersectionUnionPagingIT.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class IntersectionUnionPagingIT extends AbstractIteratingQueryIT {
+
+    private static final Logger LOG = LoggerFactory.getLogger( IntersectionUnionPagingIT.class );
+
+    private static final String unionScan =
+            "select * where (field1Or > '00000000' OR field2Or > '00000000') AND fieldDate = '0000-00-00'";
+    private static final String scanUnion =
+            "select * where fieldDate = '0000-00-00' AND (field1Or > '00000000' OR field2Or > '00000000') ";
+
+    private static final int PAGE_SIZE = 300;
+
+
+    @Test
+    public void testUnionPagingCollection() throws Exception {
+
+
+        final CollectionIoHelper collectionIoHelper = new CollectionIoHelper( app );
+
+        Set<String> created = performSetup( collectionIoHelper );
+
+
+//        testUnionPaging( collectionIoHelper, unionScan, created );
+        testUnionPaging( collectionIoHelper, scanUnion, created );
+    }
+
+
+    @Test
+    public void testUnionPagingConnection() throws Exception {
+
+        final ConnectionHelper connectionHelper = new ConnectionHelper( app );
+
+        Set<String> created = performSetup( connectionHelper );
+
+
+        testUnionPaging( connectionHelper, unionScan, created );
+        testUnionPaging( connectionHelper, scanUnion, created );
+    }
+
+
+    private Set<String> performSetup( final IoHelper io ) throws Exception {
+        io.doSetup();
+
+        int size = ( int ) ( Query.PAGE_SIZE*2.5);
+
+        long start = System.currentTimeMillis();
+
+        LOG.info( "Writing {} entities.", size );
+
+        final String zeros = String.format( "%08d", 0 );
+
+        Set<String> names = new HashSet<String>( size );
+
+        for ( int i = 0; i < size; i++ ) {
+            Map<String, Object> entity = new HashMap<String, Object>();
+            final String name = String.valueOf( i );
+            entity.put( "name", name );
+            entity.put( "fieldDate", "0000-00-00" );
+
+            String field1 = String.format( "%08d", i + 1 );
+            String field2;
+
+            //use a value slightly smaller than page size, since we want to simulate
+            //the cursor issues with union queries
+
+            if ( i < size - 10 ) {
+                field2 = zeros;
+            }
+            else {
+                field2 = String.format( "%08d", i + 1 );
+            }
+
+            names.add( name );
+
+            entity.put( "field1Or", field1 );
+            entity.put( "field2Or", field2 );
+
+            Entity saved =  io.writeEntity( entity );
+
+            LOG.info("Writing entity with id '{}'", saved.getId());
+        }
+
+        long stop = System.currentTimeMillis();
+
+        LOG.info( "Writes took {} ms", stop - start );
+
+        return Collections.unmodifiableSet( names );
+    }
+
+
+    private void testUnionPaging( final IoHelper io, final String queryString, final Set<String> expectedResults )
+            throws Exception {
+
+
+        Set<String> newSets = new HashSet<String>( expectedResults );
+
+        //our field1Or has a result size < our page size, so it shouldn't blow up when the cursor is getting created
+        //the leaf iterator should insert it's own "no value left" into the cursor
+        Query query = Query.fromQL( queryString );
+        query.setLimit( PAGE_SIZE );
+
+        Results results;
+
+        long start = System.currentTimeMillis();
+
+        do {
+
+            // now do simple ordering, should be returned in order
+            results = io.getResults( query );
+
+            for ( int i = 0; i < results.size(); i++ ) {
+                final String name = results.getEntities().get( i ).getField("name").getValue().toString();
+
+                assertTrue( "Value should not be returned twice", newSets.contains( name ) );
+
+                newSets.remove( name );
+            }
+
+            query.setCursor( results.getCursor() );
+        }
+        while ( results.getCursor() != null );
+
+        long stop = System.currentTimeMillis();
+
+        LOG.info( "Query took {} ms to return {} entities", stop - start, expectedResults.size() );
+
+        assertEquals( "All names returned", 0, newSets.size() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByCollectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByCollectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByCollectionIT.java
new file mode 100644
index 0000000..53b6f18
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByCollectionIT.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class MultiOrderByCollectionIT extends AbstractIteratingQueryIT {
+    @Test
+    public void multiOrderByCollection() throws Exception {
+        multiOrderBy( new CollectionIoHelper( app ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionCollectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionCollectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionCollectionIT.java
new file mode 100644
index 0000000..463db4e
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionCollectionIT.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class MultiOrderByComplexUnionCollectionIT extends AbstractIteratingQueryIT {
+    @Test
+    public void multiOrderByComplexUnionCollection() throws Exception {
+        multiOrderByComplexUnion( new CollectionIoHelper( app ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionConnectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionConnectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionConnectionIT.java
new file mode 100644
index 0000000..dbfe67b
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByComplexUnionConnectionIT.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class MultiOrderByComplexUnionConnectionIT extends AbstractIteratingQueryIT {
+    @Test
+    public void multiOrderByComplexUnionConnection() throws Exception {
+        multiOrderByComplexUnion( new CollectionIoHelper( app ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByConnectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByConnectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByConnectionIT.java
new file mode 100644
index 0000000..958dd04
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/MultiOrderByConnectionIT.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class MultiOrderByConnectionIT extends AbstractIteratingQueryIT {
+
+    @Test
+    public void multOrderByConnection() throws Exception {
+        multiOrderBy( new ConnectionHelper(app) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c801a47e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/NotOrderByCollectionIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/NotOrderByCollectionIT.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/NotOrderByCollectionIT.java
new file mode 100644
index 0000000..fb7e5d3
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/NotOrderByCollectionIT.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.persistence.query;
+
+
+import org.apache.usergrid.persistence.index.guice.TestIndexModule;
+import org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(JukitoRunner.class)
+@UseModules({ TestIndexModule.class })
+public class NotOrderByCollectionIT extends AbstractIteratingQueryIT {
+    @Test
+    public void orderByWithNot() throws Exception {
+        notOrderBy( new CollectionIoHelper( app ) );
+    }
+}