Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access resources by Id in Azure DocumentDB

I just started playing with Azure DocumentDB and my excitement has turned into confusion. This thing is weird. It seems like everything (databases, collections, documents) needs to be accessed not by its id, but by its 'SelfLink'. For example:

I create a database:

public void CreateDatabase()
{
    using (var client = new DocumentClient(new Uri(endpoint), authKey))
    {
        Database db = new Database()
        {
            Id = "TestDB",
        };
        client.CreateDatabaseAsync(db).Wait();
    }
}

Then later sometime I want to create a Collection:

public void CreateCollection()
{
    using (var client = new DocumentClient(new Uri(endpoint), authKey))
    {
        DocumentCollection collection = new DocumentCollection()
        {
            Id = "TestCollection",
        };
        client.CreateDocumentCollectionAsync(databaseLink: "???", documentCollection: collection).Wait();
    }
}

The api wants a 'databaseLink' when what I'd really prefer to give it is my database Id. I don't have the 'databaseLink' handy. Does DocumentDB really expect me to pull down a list of all databases and go searching through it for the databaseLink everytime I want to do anything?

This problem goes all the way down. I can't save a document to a collection without having the collection's 'link'.

public void CreateDocument()
{
    using (var client = new DocumentClient(new Uri(endpoint), authKey))
    {
        client.CreateDocumentAsync(documentCollectionLink: "???", document: new { Name = "TestName" }).Wait();
    }
}

So to save a document I need the collection's link. To get the collections link I need the database link. To get the database link I have to pull down a list of all databases in my account and go sifting through it. Then I have to use that database link that I found to pull down a list of collections in that database that I then have to sift through looking for the link of the collection I want. This doesn't seem right.

Am I missing something? Am I not understanding how to use this? Why am I assigning ids to all my resources when DocumentDB insists on using its own link scheme to identify everything? My question is 'how do I access DocumentDB resources by their Id?'

like image 561
BowserKingKoopa Avatar asked Aug 25 '14 16:08

BowserKingKoopa


3 Answers

The information posted in other answers from 2014 is now somewhat out of date. Direct addressing by Id is possible:

Although _selflinks still exist, and can be used to access resources, Microsoft have since added a much simpler way to locate resources by their Ids that does not require you to retain the _selflink :

UriFactory

UriFactory.CreateDocumentCollectionUri(databaseId, collectionId))

UriFactory.CreateDocumentUri(databaseId, collectionId, "document id");

This enables you to create a safe Uri (allowing for example for whitespace) - which is functionally identical to the resources _selflink; the example given in the Microsoft announcement is shown below:

// 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);

The announcement, from August 13th 2015, can be found here:

https://azure.microsoft.com/en-us/blog/azure-documentdb-bids-fond-farewell-to-self-links/

like image 76
dmcquiggin Avatar answered Oct 21 '22 08:10

dmcquiggin


I would recommend you look at the code samples here in particular the DocumentDB.Samples.ServerSideScripts project.

In the Program.cs you will find the GetOrCreateDatabaseAsync method:

/// <summary> 
/// Get or create a Database by id
/// </summary> 
/// <param name="id">The id of the Database to search for, or create.</param> 
/// <returns>The matched, or created, Database object</returns> 
private static async Task<Database> GetOrCreateDatabaseAsync(string id) 
{ 
    Database database = client.CreateDatabaseQuery()
        .Where(db => db.Id == id).ToArray().FirstOrDefault(); 
    if (database == null) 
    { 
        database = await client.CreateDatabaseAsync(
            new Database { Id = id }); 
    } 

    return database; 
} 

To answer you question, you can use this method to find your database by its id and other resources (collections, documents etc.) using their respective Create[ResourceType]Query() methods.

Hope that helps.

like image 7
Robert C Navarro Avatar answered Oct 21 '22 07:10

Robert C Navarro


The create database call returns a the database object:

var database = client.CreateDatabaseAsync(new Database { Id = databaseName }).Result.Resource;

And then you can use that to create your collection

var spec = new DocumentCollection { Id = collectionName };
spec.IndexingPolicy.IndexingMode = IndexingMode.Consistent;
spec.IndexingPolicy.Automatic = true;
spec.IndexingPolicy.IncludedPaths.Add(new IndexingPath { IndexType = IndexType.Range, NumericPrecision = 6, Path = "/" });
var options = new RequestOptions
{
    ConsistencyLevel = ConsistencyLevel.Session
};

var collection = client.CreateDocumentCollectionAsync(database.SelfLink, spec, options).Result.Resource;
like image 1
Renato Ferreira Avatar answered Oct 21 '22 06:10

Renato Ferreira