/// <summary>
        /// When resuming an order by query we need to filter the document producers.
        /// </summary>
        /// <param name="producer">The producer to filter down.</param>
        /// <param name="sortOrders">The sort orders.</param>
        /// <param name="continuationToken">The continuation token.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task to await on.</returns>
        private async Task FilterAsync(
            ItemProducerTree producer,
            SortOrder[] sortOrders,
            OrderByContinuationToken continuationToken,
            CancellationToken cancellationToken)
        {
            // When we resume a query on a partition there is a possibility that we only read a partial page from the backend
            // meaning that will we repeat some documents if we didn't do anything about it.
            // The solution is to filter all the documents that come before in the sort order, since we have already emitted them to the client.
            // The key is to seek until we get an order by value that matches the order by value we left off on.
            // Once we do that we need to seek to the correct _rid within the term,
            // since there might be many documents with the same order by value we left off on.

            foreach (ItemProducerTree tree in producer)
            {
                if (!ResourceId.TryParse(continuationToken.Rid, out ResourceId continuationRid))
                {
                    throw new CosmosException(
                              statusCode: HttpStatusCode.BadRequest,
                              message: $"Invalid Rid in the continuation token {continuationToken.CompositeContinuationToken.Token} for OrderBy~Context.");
                }

                Dictionary <string, ResourceId> resourceIds = new Dictionary <string, ResourceId>();
                int  itemToSkip = continuationToken.SkipCount;
                bool continuationRidVerified = false;

                while (true)
                {
                    OrderByQueryResult orderByResult = new OrderByQueryResult(tree.Current);
                    // Throw away documents until it matches the item from the continuation token.
                    int cmp = 0;
                    for (int i = 0; i < sortOrders.Length; ++i)
                    {
                        cmp = ItemComparer.Instance.Compare(
                            continuationToken.OrderByItems[i].Item,
                            orderByResult.OrderByItems[i].Item);

                        if (cmp != 0)
                        {
                            cmp = sortOrders[i] != SortOrder.Descending ? cmp : -cmp;
                            break;
                        }
                    }

                    if (cmp < 0)
                    {
                        // We might have passed the item due to deletions and filters.
                        break;
                    }

                    if (cmp == 0)
                    {
                        ResourceId rid;
                        if (!resourceIds.TryGetValue(orderByResult.Rid, out rid))
                        {
                            if (!ResourceId.TryParse(orderByResult.Rid, out rid))
                            {
                                throw new CosmosException(
                                          statusCode: HttpStatusCode.BadRequest,
                                          message: $"Invalid Rid in the continuation token {continuationToken.CompositeContinuationToken.Token} for OrderBy~Context~TryParse.");
                            }

                            resourceIds.Add(orderByResult.Rid, rid);
                        }

                        if (!continuationRidVerified)
                        {
                            if (continuationRid.Database != rid.Database || continuationRid.DocumentCollection != rid.DocumentCollection)
                            {
                                throw new CosmosException(
                                          statusCode: HttpStatusCode.BadRequest,
                                          message: $"Invalid Rid in the continuation token {continuationToken.CompositeContinuationToken.Token} for OrderBy~Context.");
                            }

                            continuationRidVerified = true;
                        }

                        // Once the item matches the order by items from the continuation tokens
                        // We still need to remove all the documents that have a lower rid in the rid sort order.
                        // If there is a tie in the sort order the documents should be in _rid order in the same direction as the first order by field.
                        // So if it's ORDER BY c.age ASC, c.name DESC the _rids are ASC
                        // If ti's ORDER BY c.age DESC, c.name DESC the _rids are DESC
                        cmp = continuationRid.Document.CompareTo(rid.Document);
                        if (sortOrders[0] == SortOrder.Descending)
                        {
                            cmp = -cmp;
                        }

                        // We might have passed the item due to deletions and filters.
                        // We also have a skip count for JOINs
                        if (cmp < 0 || (cmp == 0 && itemToSkip-- <= 0))
                        {
                            break;
                        }
                    }

                    (bool successfullyMovedNext, QueryResponseCore? failureResponse)moveNextResponse = await tree.MoveNextAsync(cancellationToken);

                    if (!moveNextResponse.successfullyMovedNext)
                    {
                        if (moveNextResponse.failureResponse != null)
                        {
                            this.FailureResponse = moveNextResponse.failureResponse;
                        }

                        break;
                    }
                }
            }
        }
        public void TestRoundTripAsCosmosElement()
        {
            CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken()
            {
                Token = "someToken",
                Range = new Documents.Routing.Range <string>("asdf", "asdf", false, false),
            };

            List <OrderByItem> orderByItems = new List <OrderByItem>()
            {
                new OrderByItem(CosmosObject.Create(new Dictionary <string, CosmosElement>()
                {
                    { "item", CosmosString.Create("asdf") }
                })),
                new OrderByItem(CosmosObject.Create(new Dictionary <string, CosmosElement>()
                {
                    { "item", CosmosInt64.Create(1337) }
                })),
                new OrderByItem(CosmosObject.Create(new Dictionary <string, CosmosElement>()
                {
                    { "item", CosmosBinary.Create(new byte[] { 1, 2, 3 }) }
                })),
            };

            string rid       = "someRid";
            int    skipCount = 42;
            string filter    = "someFilter";
            OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken(
                compositeContinuationToken,
                orderByItems,
                rid,
                skipCount,
                filter);

            CosmosElement cosmosElementToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken);

            Assert.AreEqual(
                @"{""compositeToken"":{""token"":""someToken"",""range"":{""min"":""asdf"",""max"":""asdf""}},""orderByItems"":[{""item"":""asdf""},{""item"":LL1337},{""item"":BAQID}],""rid"":""someRid"",""skipCount"":42,""filter"":""someFilter""}",
                cosmosElementToken.ToString());
            TryCatch <OrderByContinuationToken> tryOrderByContinuationTokenFromCosmosElement = OrderByContinuationToken.TryCreateFromCosmosElement(cosmosElementToken);

            Assert.IsTrue(tryOrderByContinuationTokenFromCosmosElement.Succeeded);
            OrderByContinuationToken orderByContinuationTokenFromCosmosElement = tryOrderByContinuationTokenFromCosmosElement.Result;

            Assert.IsNotNull(orderByContinuationTokenFromCosmosElement);
            Assert.AreEqual(cosmosElementToken.ToString(), OrderByContinuationToken.ToCosmosElement(orderByContinuationTokenFromCosmosElement).ToString());
        }