Benoit Patra Benoit Patra - 6 days ago 6
C# Question

Querying objects properties with .NET DocumentDB SDK

I have a .NET POCO class for my DocumentDB documents.

public class FatDocument{
public string id { get; set; }

public string LightProperty { get;set;}
public string LightProperty2 { get;set;}

public string FatProperty { get;set;}
}


As the name suggest, FatProperty contains most of the information of the Document. All documents in my DocumentDB collection are actually JSON serialized version of FatDocument.

For many purposes in my business application I do not need to retrieve the FatProperty. In order to save some RUs, I created a light version of the POCO.

public class LightDocument{
public string id { get; set; }

public string LightProperty { get;set;}
public string LightProperty2 { get;set;}
}

public class FatDocument: LightDocument{
public string FatProperty { get;set;}
}


Now I am looking for a way to retrieve an
IQueryable<LightDocument>
.

If I create a
QueryDocument
with
client.CreateDocumentQuery<LightDocument>
, after execution, this IQueryable returns a LightDocument enumeration. But after DocumentDB request inspection we saw a
SELECT * FROM
. This is not what we are looking for, we want to ignore
FatProperty
in DocumentDB query to save some RUs (and request payload between client app and DocumentDB).

I also tried combining the creation of the query using SQL syntax

var queryspec = new SqlQuerySpec() { QueryText = "SELECT c.id, c.LightProperty, c.LightProperty2"};
var queryable = client.CreateDocumentQuery<LightDocument>(GetDocUri(), queryspec);
queryable.Where(c => /* Some filtering logic */);
queryable.AsEnumerable(); //EXCEPTION thrown


This throws an Exception
Method 'AsSQL' is not supported. Only LINQ Methods are supported
.

Note: inverting AsEnumerable and Where is not an option here. We want the
where
clause to be translated into a DocumentDB where clause.

My question is: how could I create LINQ queries with DocumentDB .NET SDK returning partial documents?

Answer

If you are using LINQ instead of SQL queries, you can use the .Select() method on the IQueriable to project the fat document to the light document. Then you can chain the result to the .Where() method.

Light Document Query

var lightDocumentQuery = client.CreateDocumentQuery<LightDocument>(GetCollectionLink())
                                .Select(d => new LightDocument { id = d.id, LightProperty = d.LightProperty, LightProperty2 = d.LightProperty2 })
                                .Where(d => d.LightProperty == compareTo)
                                .AsDocumentQuery();  

Light Document Result

{  
  "id": "9d4ec687-95a5-68df-d51d-5d2fb0143231",  
  "LightProperty": "someValue",
  "LightProperty2": "someOtherValue"
}

Fat Document Query

var fatDocumentQuery = client.CreateDocumentQuery<FatDocument>(GetCollectionLink())
                            .Where(d => d.LightProperty == compareTo)
                            .AsDocumentQuery();

Fat Document Result

{  
  "FatProperty": "SomeFatProperty usually json",  
  "id": "9d4ec687-95a5-68df-d51d-5d2fb0143231",  
  "LightProperty": "someValue",  
  "LightProperty2": "someOtherValue"  
}

The resulting query in the light document example does not reference the FatProperty so it is not sent over the wire. I went ahead and checked the RUs for each request type and they were almost even, with the FatDocument query costing slightly more, which is reasonable since there is more bandwidth being used.

  • LightDocument Query RU: 3.05
  • FatDocument Query RU: 3.09
Comments