• 4 min read

Azure DocumentDB bids fond farewell to Self-Links

How to get started with the new and improved id-based routing in DocumentDB.

Ok, I admit it, that title is misleading because we’re not getting rid of self-links entirely. I’ll explain more in a bit, but first let’s pause for a moment to reflect on how and why DocumentDB uses self-links in the first place. Azure DocumentDB is a fully managed JSON document database service hosted on Microsoft Azure, accessible via a REST interface. As a REST service, every resource in DocumentDB is addressable by a uniform resource identifier (Uri). The DocumentDB resource model explains how all resources relate to each other and how these Uris are structured following this resource model. A resource id is a unique, immutable, system generated value. If you inspect any resource in DocumentDB you will see some system properties, identified by an underscore (“_”) character. One of these system properties, _rid, is this resource id. JSON document with system properties Another one of the system properties is _self, which is the self-link for this resource. The self-link is a Uri in the form of “dbs/{0}/colls/{1}/docs/{2}”; where {0} is the database _rid, {1} is the _rid for the document collection, and {2} is the _rid for the document. If you have done any work with DocumentDB you are likely quite familiar with Uris that look like this; because they are used anytime you do anything with any resource in the database. Being able to address a resource with a Uri like a self-link is a great thing because it provides a stable Uri that can be used to address the resource. So why are we getting rid of them? Well, we haven’t removed self-links. Not entirely. We’ve heard from many customers that these _rid based self-links are really difficult to work with because nobody knows what the resource id is offhand. You have to query for the resource just to get its self-link before you can do anything with that resource. Customers ask, “Every resource has an id, which I set when creating the resource, so why can’t I use that id when addressing the resource?” We agree with this sentiment, which is why today we’re announcing a big change in this area. Documents will still have a _self property but we’re now adding the ability to build up an alternative link to a resource that is based on the id, and not the _rid. (Note: The ability to use the existing self-link on the resource is still supported.) This means that the following Uri is now a valid way to reference the document we looked at earlier. dbs/MyDatabaseId/colls/MyCollectionId/docs/MyDocumentId NB – notice how this URI does not end with a trailing '/' character. This is a subtle, but important difference. Not only is this easier on the eye, but more importantly you can now use the id you supplied when creating the resource as part of this Uri. Up until now, if you wanted to do a simple operation such as deleting a document you needed to write code similar to the following:

// Get a Database by querying for it by id
Database db = client.CreateDatabaseQuery()
                    .Where(d => d.Id == "SalesDb")
                    .AsEnumerable()
                    .Single();

// Use that Database's SelfLink to query for a DocumentCollection by id
DocumentCollection coll = client.CreateDocumentCollectionQuery(db.SelfLink)
                                .Where(c => c.Id == "Catalog")
                                .AsEnumerable()
                                .Single();

// Use that Collection's SelfLink to query for a DocumentCollection by id
Document doc = client.CreateDocumentQuery(coll.SelfLink)
                     .Where(d => d.Id == "prd123")
                     .AsEnumerable()
                     .Single();

// Now that we have a doc, use it's SelfLink property to delete it
await client.DeleteDocumentAsync(doc.SelfLink);

That’s a lot of code, the majority of which is simple boilerplate code to lookup resources in order to get the self-links needed. The code snippet has three calls to the service, each costing you request units and network roundtrips, before you can perform the operation you wanted to do. With this release, you can replace that code with the following two lines of code:

// Build up a link manually using ids
// If you are building up links manually, ensure that 
// the link does not end with a trailing '/' character
var docLink = string.Format("dbs/{0}/colls/{1}/docs/{2}", 
     "SalesDb", "Catalog", "prd123");

// Use this constructed link to delete the document
await client.DeleteDocumentAsync(docLink);

Not only does this result in less code to write and maintain, but it also results in fewer database operations leaving those RUs for more important things like writing documents. The code above still requires you understand how to build up the Uri correctly from the resource model. You also need to do things like escape whitespace and encode special characters to ensure you have a valid Uri, so we went one step further in the SDK and added a simple helper factory to do this for you.

// Use UriFactory to build the DocumentLink
Uri docUri = UriFactory.CreateDocumentUri("SalesDb", "Catalog", "prd123");

// Use this constructed Uri to delete the document
await client.DeleteDocumentAsync(docUri);

With this new UriFactory class, all you have to know is the kind of Uri you need and the appropriate ids. To take advantage of these changes and get access to the UriFactory class, you will need to update your applications to use version 1.4.0 (or greater) of the .NET SDK. For our Node.js, Python, and Java SDKs, no updates are required, just craft your new alternate links and enjoy! If you would like a more comprehensive sample that demonstrates the use of this ID-based routing, try this project we put together. Please keep the feedback coming for the features that are most important to you using our feedback forum. It’s this feedback that helps us improve the service with updates just like this one. To stay up to date on the latest DocumentDB news and features, follow us on Twitter @DocumentDB. If you haven’t tried DocumentDB yet, get started here and point your browser at the learning path to help you get on your way.