【问题标题】:Querying objects properties with .NET DocumentDB SDK使用 .NET DocumentDB SDK 查询对象属性
【发布时间】:2016-11-28 13:25:13
【问题描述】:

我的 DocumentDB 文档有一个 .NET POCO 类。

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

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

   public string FatProperty { get;set;}    
}

顾名思义,FatProperty 包含了 Document 的大部分信息。 我的 DocumentDB 集合中的所有文档实际上都是 FatDocument 的 JSON 序列化版本

对于我的业务应用程序中的许多目的,我不需要检索 FatProperty。 为了节省一些 RU,我创建了一个轻量版的 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;}
}

现在我正在寻找一种方法来检索IQueryable<LightDocument>

如果我用client.CreateDocumentQuery<LightDocument> 创建一个QueryDocument,在执行之后,这个IQueryable 返回一个LightDocument 枚举。但在 DocumentDB 请求检查后,我们看到了 SELECT * FROM。这不是我们要寻找的,我们想在 DocumentDB 查询中忽略 FatProperty 以保存一些 RU(并在客户端应用程序和 DocumentDB 之间请求有效负载)。

我还尝试使用 SQL 语法组合查询的创建

 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

这会引发异常Method 'AsSQL' is not supported. Only LINQ Methods are supported

注意: 反转 AsEnumerable 和 Where 不是一个选项。我们希望将where 子句翻译成 DocumentDB where 子句。

我的问题是:如何使用 DocumentDB .NET SDK 返回部分文档来创建 LINQ 查询?

【问题讨论】:

  • JamyRyals 对此有最好的解决方案 - 通过使用 Select 进行投影。我还建议检查此更改是否会导致 RU 发生重大变化。一般来说,额外属性的投影不会导致 RU 有很大差异。
  • 我在请求单位方面获得了 x2 增益!

标签: c# linq azure-cosmosdb


【解决方案1】:

如果您使用 LINQ 而不是 SQL 查询,则可以使用 IQueriable 上的 .Select() 方法将胖文档投影到轻文档。然后您可以将结果链接到 .Where() 方法。

轻量级文档查询

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

轻量级文档结果

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

胖文档查询

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

胖文件结果

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

轻文档示例中生成的查询没有引用 FatProperty,因此它不会通过网络发送。我继续检查每种请求类型的 RU,它们几乎是均匀的,FatDocument 查询的成本略高,这是合理的,因为使用了更多的带宽。

  • LightDocument 查询 RU:3.05
  • FatDocument 查询 RU:3.09

【讨论】:

  • 实际上您需要重新创建“光实体”才能使选择生效。我试过Select(d =&gt; (LightDocument) d),但它不起作用。您需要在.Select 语句中重新创建对象.Select(c =&gt; new LightDocument(){ /*Copy properties */}
  • 为了这个例子我简化了,但在我的例子中,通过丢弃一个胖属性,它是一个具有自己索引的“丰富”对象,而不仅仅是一个普通的旧字符串,我真的得到了一些RU 方面的显着收益。
  • 这很有道理,Benoit。
猜你喜欢
  • 1970-01-01
  • 2017-08-27
  • 2015-01-17
  • 2021-05-16
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多