6

A container has a function called ReadItemAsync. The problem is I do not have the partition key, but only the id of the document. What is the best approach to get just a single item then?

Do I have to get it from a collection? Like:

var allItemsQuery = VesselContainer.GetItemQueryIterator<CoachVessel>("SELECT * FROM c where c.id=....");

var q = VesselContainer.GetItemLinqQueryable<CoachVessel>();
var iterator = q.ToFeedIterator();

var result = new List<CoachVessel>();
while (iterator.HasMoreResults)
{
    foreach (var item in await iterator.ReadNextAsync())
    {
        result.Add(item);
    }
}
2
  • Yes you have to do a fan out query but id is only distinct per partition key so even then you may end up with multiple items. Frankly speaking, if you don't have the partition key for a point read then the model for the database is not correct. It should be redesigned. Commented Jul 9, 2020 at 17:13
  • Unfortunately data is coming from an external API and I cannot ask them to redesign. But thanks for your reply. Can you create an answer that states it is not possible to do it without partition key. Commented Jul 9, 2020 at 19:25

2 Answers 2

9

Posting as answer.

Yes you have to do a fan out query but id is only distinct per partition key so even then you may end up with multiple items. Frankly speaking, if you don't have the partition key for a point read then the model for the database is not correct. It (or the application itself) should be redesigned.

Additionally. For small, single partition collections this x-partition query will not be too expensive as the collection is small. However, once the database starts to scale out this will get increasingly slower and more expensive as the query will fan out to ever increasing numbers of physical partitions. As stated above, I would strongly recommend you modify the app to pass the partition key value in the request. This will allow you to do a single point read operation which is extremely fast and efficient.

Good luck.

Sign up to request clarification or add additional context in comments.

3 Comments

I didn't realise passing the partition key in the request would be a good practice, but I am still unsure about picking a partition key. When you want to retrieve a single item in a collection, how could you possibly always know the partition key?
The partition key should ideally be innate to the data itself. For instance, when looking up a customer, you ideally would use some piece of data that is associated with the customer. Maybe it's a phone number, maybe its something else. If you're new to modeling data for this type of database I definitely recommend reading this article. Most people get an "aha" moment when they read it. learn.microsoft.com/en-us/azure/cosmos-db/…
@MarkBrown thanks for the link, really good one. It teaches to don't be afraid of the denormalization and it's "ugliness" (and it is VERY ugly, as for me).
1

Try using ReadItemAsync like:

dynamic log = await container.ReadItemAsync<dynamic>(ID, PartitionKey.None);

1 Comment

This is not correct. If the field is defined (i.e. customer_name) and you have a value in it (i.e. BoA) then it will not perform a cross partition search. It will instead throw a not found error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.