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

akn*_*ds1 2 .net c# 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"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

如何在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; } 
}
Run Code Online (Sandbox Code Playgroud)

akn*_*ds1 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
                             };
    }
}
Run Code Online (Sandbox Code Playgroud)

查询本身:

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

此查询成功查找具有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>()
Run Code Online (Sandbox Code Playgroud)