@@ -31,7 +31,7 @@ public CosmosQueryEngine(CosmosClientProvider clientProvider, IMetadataStoreProv
3131 /// Executes the given IMiddlewareContext of the GraphQL query and
3232 /// expecting a single Json back.
3333 /// </summary>
34- public async Task < JsonDocument > ExecuteAsync ( IMiddlewareContext context , IDictionary < string , object > parameters )
34+ public async Task < JsonDocument > ExecuteAsync ( IMiddlewareContext context , IDictionary < string , object > parameters , bool isPaginatedQuery )
3535 {
3636 // TODO: fixme we have multiple rounds of serialization/deserialization JsomDocument/JObject
3737 // TODO: add support for nesting
@@ -41,6 +41,10 @@ public async Task<JsonDocument> ExecuteAsync(IMiddlewareContext context, IDictio
4141 string graphQLQueryName = context . Selection . Field . Name . Value ;
4242 GraphQLQueryResolver resolver = this . _metadataStoreProvider . GetQueryResolver ( graphQLQueryName ) ;
4343 Container container = this . _clientProvider . Client . GetDatabase ( resolver . DatabaseName ) . GetContainer ( resolver . ContainerName ) ;
44+
45+ QueryRequestOptions queryRequestOptions = new ( ) ;
46+ string requestContinuation = null ;
47+
4448 QueryDefinition querySpec = new ( resolver . ParametrizedQuery ) ;
4549
4650 if ( parameters != null )
@@ -51,7 +55,42 @@ public async Task<JsonDocument> ExecuteAsync(IMiddlewareContext context, IDictio
5155 }
5256 }
5357
54- FeedResponse < JObject > firstPage = await container . GetItemQueryIterator < JObject > ( querySpec ) . ReadNextAsync ( ) ;
58+ if ( parameters . TryGetValue ( "first" , out object maxSize ) )
59+ {
60+ queryRequestOptions . MaxItemCount = Convert . ToInt32 ( maxSize ) ;
61+ }
62+
63+ if ( parameters . TryGetValue ( "after" , out object after ) )
64+ {
65+ requestContinuation = Base64Decode ( after as string ) ;
66+ }
67+
68+ FeedResponse < JObject > firstPage = await container . GetItemQueryIterator < JObject > ( querySpec , requestContinuation , queryRequestOptions ) . ReadNextAsync ( ) ;
69+
70+ if ( isPaginatedQuery )
71+ {
72+ JArray jarray = new ( ) ;
73+ IEnumerator < JObject > enumerator = firstPage . GetEnumerator ( ) ;
74+ while ( enumerator . MoveNext ( ) )
75+ {
76+ JObject item = enumerator . Current ;
77+ jarray . Add ( item ) ;
78+ }
79+
80+ string responseContinuation = firstPage . ContinuationToken ;
81+ if ( string . IsNullOrEmpty ( responseContinuation ) )
82+ {
83+ responseContinuation = null ;
84+ }
85+
86+ JObject res = new (
87+ new JProperty ( "endCursor" , Base64Encode ( responseContinuation ) ) ,
88+ new JProperty ( "hasNextPage" , responseContinuation != null ) ,
89+ new JProperty ( "nodes" , jarray ) ) ;
90+
91+ // This extra deserialize/serialization will be removed after moving to Newtonsoft from System.Text.Json
92+ return JsonDocument . Parse ( res . ToString ( ) ) ;
93+ }
5594
5695 JObject firstItem = null ;
5796
@@ -111,5 +150,28 @@ public Task<JsonDocument> ExecuteAsync(FindRequestContext queryStructure)
111150 {
112151 throw new NotImplementedException ( ) ;
113152 }
153+
154+ private static string Base64Encode ( string plainText )
155+ {
156+ if ( plainText == default )
157+ {
158+ return null ;
159+ }
160+
161+ byte [ ] plainTextBytes = System . Text . Encoding . UTF8 . GetBytes ( plainText ) ;
162+ return System . Convert . ToBase64String ( plainTextBytes ) ;
163+ }
164+
165+ private static string Base64Decode ( string base64EncodedData )
166+ {
167+ if ( base64EncodedData == default )
168+ {
169+ return null ;
170+ }
171+
172+ byte [ ] base64EncodedBytes = System . Convert . FromBase64String ( base64EncodedData ) ;
173+ return System . Text . Encoding . UTF8 . GetString ( base64EncodedBytes ) ;
174+ }
175+
114176 }
115177}
0 commit comments