RavenDB - 如何查询对象的属性及其子对象

时间:2013-07-20 21:20:22

标签: c# .net nosql ravendb

我的问题是根据每个文档的属性及其子代的属性从C#中选择RavenDB文档。假设我们有以下文件:

objekts/1:
  {
  "Code": "1",
  "Children": [
    {
      "Role": "A",
      "Place": "Here"
    },
    {
      "Role": "B",
      "Place": "There"
    }
  ]
}

objekts/2:
{
  "Code": "1",
  "Children": [
    {
      "Role": "A",
      "Place": "There"
    },
    {
      "Role": "B",
      "Place": "Here"
    }
  ]
}

如何在C#中制定查询以选择具有Code ==“1”的对象,并且至少有一个具有Role ==“A”且Place ==“There”的子项?该查询应解析为objekts/2

另外,我如何制定一个我可以查询的相应Raven索引?

数据类

public class Child
{
    public string Role { get; set; }
    public string Place { get; set; }
}

public class Objekt
{
    public string Code { get; set; }
    public List<Child> Children { get; set; } 
}

1 个答案:

答案 0 :(得分:5)

首先,我们将处理索引,请注意子键的前缀为Children_(Raven要求):

public class Objekt_ByCodeAndChildren : AbstractIndexCreationTask<Objekt>
{
    public Objekt_ByCodeAndChildren()
    {
        Map = objekts => from objekt in objekts
                         from child in objekt.Children
                             select new
                             {
                                 objekt.Code,
                                 Children_Role = child.Role,
                                 Children_Place = child.Place
                             };
    }
}

查询本身:

session.Query<Objekt, Objekt_ByCodeAndChildren>()
    .Where(o => o.Code == "1" &&
        o.Children.Any(c => c.Role == "A" && c.Place == "There"));

此查询成功找到ID为objekts/2的文档,因为匹配o.Children.Any(c => c.Role == "A" && c.Place == "There")的子项需要为索引子键添加前缀Children_ (例如,Children_Role)。

另一种技术是查询索引键类型,并将结果转换为原始类型(例如Objekt):

// Index key representation of an Objekt
public class ObjektKey
{
    public string Code { get; set; }
    public string Role { get; set; }
    public string Place { get; set; }
}

// Query for ObjektKey instances, before finally transforming them to Objekt
session.Query<ObjektKey, Objekt_ByCodeAndChildren>()
            .Where(o => o.Code == "1" && o.Role == "A" && o.Place == "Here")
            .OfType<Objekt>()