Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read Azure DocumentDB document that might not exist

I can query a single document from the Azure DocumentDB like this:

var response = await client.ReadDocumentAsync( documentUri );

If the document does not exist, this will throw a DocumentClientException. In my program I have a situation where the document may or may not exist. Is there any way to query for the document without using try-catch and without doing two round trips to the server, first to query for the document and second to retrieve the document should it exist?

like image 411
Tuukka Haapaniemi Avatar asked Feb 18 '16 13:02

Tuukka Haapaniemi


2 Answers

Sadly there is no other way, either you handle the exception or you make 2 calls, if you pick the second path, here is one performance-driven way of checking for document existence:

public bool ExistsDocument(string id)
{
    var client = new DocumentClient(DatabaseUri, DatabaseKey);
    var collectionUri = UriFactory.CreateDocumentCollectionUri("dbName", "collectioName");
    var query = client.CreateDocumentQuery<Microsoft.Azure.Documents.Document>(collectionUri, new FeedOptions() { MaxItemCount = 1 });
    return query.Where(x => x.Id == id).Select(x=>x.Id).AsEnumerable().Any(); //using Linq
}

The client should be shared among all your DB-accesing methods, but I created it there to have a auto-suficient example.

The new FeedOptions () {MaxItemCount = 1} will make sure the query will be optimized for 1 result (we don't really need more).

The Select(x=>x.Id) will make sure no other data is returned, if you don't specify it and the document exists, it will query and return all it's info.

like image 126
Matias Quaranta Avatar answered Oct 22 '22 20:10

Matias Quaranta


You're specifically querying for a given document, and ReadDocumentAsync will throw that DocumentClientException when it can't find the specific document (returning a 404 in the status code). This is documented here. By catching the exception (and seeing that it's a 404), you wouldn't need two round trips.

To get around dealing with this exception, you'd need to make a query instead of a discrete read, by using CreateDocumentQuery(). Then, you'll simply get a result set you can enumerate through (even if that result set is empty). For example:

var collLink = UriFactory.CreateDocumentCollectionUri(databaseId, collectionId);
var querySpec = new SqlQuerySpec { <querytext> };

var itr = client.CreateDocumentQuery(collLink, querySpec).AsDocumentQuery();
var response = await itr.ExecuteNextAsync<Document>();

foreach (var doc in response.AsEnumerable())
{
    // ...
}

With this approach, you'll just get no responses. In your specific case, where you'll be adding a WHERE clause to query a specific document by its id, you'll either get zero results or one result.

like image 22
David Makogon Avatar answered Oct 22 '22 18:10

David Makogon