Azure / azure-sdk-for-js

This repository is for active development of the Azure SDK for JavaScript (NodeJS & Browser). For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/javascript/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-js.
MIT License
2.04k stars 1.19k forks source link

Support cross-partition continuation tokens in node.js SDK #20140

Closed sajeetharan closed 6 months ago

sajeetharan commented 2 years ago

Right now, node.js SDK only supports continuation tokens for single partition queries. This is a request for cross-partition continuation token support in the node.js SDK.

exiledwolfking commented 1 year ago

is this still not possible? my partition key is the id field and i want to paginate my results using a continuation token. if i use the following the only headers i get back are 'x-ms-request-charge' and 'x-ms-documentdb-query-metrics'. no continuation token

    const results = await db
      .database(process.env.DATABASE_ID)
      .container('ratings')
      .items.query(querySpec, {
        maxItemCount: 2,
        enableCrossPartitionQuery: true,
        continuationToken: continuationToken ? continuationToken : null,
      })
      .fetchNext()
sajeetharan commented 1 year ago

@topshot99 can you check?

topshot99 commented 1 year ago

@exiledwolfking To help us reproduce the issue, could you provide the querySpec, SDK version, and response that you're currently receiving?

exiledwolfking commented 1 year ago

Sure. I am on @azure/cosmos 3.17.3. querySpec:

querySpec = {
  query: `
        SELECT * FROM c
        WHERE c.userId = @userId
        ORDER BY c.createdOn desc
  `,
  parameters: [{ name: '@userId', value: userId }]
}

response:

{
  resources: [{id: '<id>', ...}, {id: '<id>', ...}], // two resources 
  headers: { 'x-ms-request-charge': 5.77, 'x-ms-documentdb-query-metrics': {} },
  hasMoreResults: true,
}

thats with these as options:

 maxItemCount: 2,
 continuationToken: null,
 enableCrossPartitionQuery: true

If I add the partitionKey property in the query options so that it matches one of my object's ids (id is my partition key), then i get a bunch of headers back. Obviously it only returns the one item with that id though.

headers = {
'cache-control': 'no-store, no-cache',
pragma: 'no-cache',
'transfer-encoding': 'chunked',
'content-type': 'application/json',
server: 'Microsoft-HTTPAPI/2.0',
'strict-transport-security': 'max-age=31536000',
'x-ms-activity-id': '574862da-14b6-42a6-9eb0-8bd3ba865c14',
'x-ms-last-state-change-utc': 'Fri, 17 Mar 2023 18:31:23.150 GMT',
'x-ms-resource-quota': 'documentSize=51200;documentsSize=52428800;documentsCount=-1;collectionSize=52428800;',
'x-ms-resource-usage': 'documentSize=0;documentsSize=162;documentsCount=39;collectionSize=172;',
'x-ms-schemaversion': '1.15',
lsn: '979',
'x-ms-item-count': '1',
'x-ms-request-charge': '2.93',
'x-ms-alt-content-path': 'dbs/game-rater/colls/ratings',
'x-ms-content-path': 'nuJhAKC+4dE=',
'x-ms-documentdb-partitionkeyrangeid': '0',
'x-ms-xp-role': '1',
'x-ms-cosmos-query-execution-info': '{"reverseRidEnabled":false,"reverseIndexScan":true}',
'x-ms-global-committed-lsn': '978',
'x-ms-number-of-read-regions': '0',
'x-ms-transport-request-id': '7',
'x-ms-cosmos-llsn': '979',
'x-ms-session-token': '0:-1#979',
'x-ms-request-duration-ms': '0.809',
'x-ms-serviceversion': 'version=2.14.0.0',
'x-ms-cosmos-is-partition-key-delete-pending': 'false',
'x-ms-gatewayversion': 'version=2.14.0',
date: 'Fri, 31 Mar 2023 00:39:02 GMT',
'x-ms-throttle-retry-count': 0,
'x-ms-throttle-retry-wait-time-ms': 0
}
topshot99 commented 1 year ago

Hey @exiledwolfking,

At the moment, you can use the following approach:

const container = await db.container(process.env.CONTAINER_NAME);
const queryOptions = {
        maxItemCount: 2,
        enableCrossPartitionQuery: true,
      }
  const querIterator = await container.items.query(querySpec, queryOptions);

while (querIterator.hasMoreResults()) {
        const { resources: result } = await querIterator.fetchNext();
        //Do something with result
}

With this method, the query iterator is initialized only once, and all the data is retrieved using the iterator. The SDK handles everything in this case(even cross partition queries).

We are currently working on a solution to retrieve the continuation token for cross partition queries.

exiledwolfking commented 1 year ago

Okay thanks for the help. Looking forward to to it

On Mon, Apr 3, 2023, 1:29 AM Manik Khandelwal @.***> wrote:

Hey @exiledwolfking https://github.com/exiledwolfking,

At the moment, you can use the following approach:

` const container = await db.container(process.env.CONTAINER_NAME); const queryOptions = { maxItemCount: 2, enableCrossPartitionQuery: true, } const querIterator = await container.items.query(querySpec, queryOptions);

while (querIterator.hasMoreResults()) { const { resources: result } = await querIterator.fetchNext(); //Do something with result } ` With this method, the query iterator is initialized only once, and all the data is retrieved using the iterator. The SDK handles everything in this case.

We are currently working on a solution to retrieve the continuation token from the headers, which will be available soon.

— Reply to this email directly, view it on GitHub https://github.com/Azure/azure-sdk-for-js/issues/20140#issuecomment-1493743035, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADFXLYM2QJR7RHK6VTCE6MTW7JU6FANCNFSM5NGXFPTQ . You are receiving this because you were mentioned.Message ID: @.***>

diiiego83 commented 1 year ago

Hello,

is there any update on this? it will be great to enable pagination on a cross partition model.

Thanks

topshot99 commented 1 year ago

Hey @diiiego83 , Pagination is available for cross-partition models, but we currently do not support continuation tokens for aggregate queries (e.g., order by, sum) across partitions. However, in our readme, we have provided a workaround that you can use to address this. Link: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/cosmosdb/cosmos/README.md#executing-non-stremable-cross-partition-query

diiiego83 commented 1 year ago

@topshot99 thanks to get back to me. In case we don't use aggregation in our query will be possible works with continuation tokens? I mean send back that token to the caller so it can use iteratively in his application to retrieve the next page etc..etc..

topshot99 commented 1 year ago

@diiiego83 Indeed, it would be effective in that scenario

gausss commented 1 year ago

Hey we just ran into this issue. We'll build a java sidecar for now but do you have any time or roadmap when this will get into the Node SDK? :)

diiiego83 commented 1 year ago

@topshot99 the iteration works fine if no need to pass around the continuation token (for this we still have a sidecar). I have better results using the fetchAll() from the JS SDK. Is this method working fine for aggregation queries on cross partition? Just want to know if internally implement the same While/fetchNext() pattern. Thanks

topshot99 commented 1 year ago

Absolutely, the fetchAll() method is indeed suitable for performing aggregation queries that span multiple partitions. It's worth noting that there's no need for an internal implementation of the While/fetchNext() pattern, as fetchAll() returns all the available results/items.

github-actions[bot] commented 6 months ago

Hi @sajeetharan, we deeply appreciate your input into this project. Regrettably, this issue has remained inactive for over 2 years, leading us to the decision to close it. We've implemented this policy to maintain the relevance of our issue queue and facilitate easier navigation for new contributors. If you still believe this topic requires attention, please feel free to create a new issue, referencing this one. Thank you for your understanding and ongoing support.