使用RavenDB查询子文档列表

时间:2012-02-29 13:29:31

标签: .net c#-4.0 ravendb

给定以下对象结构:

public class Object
{
public string Id {get;set;}
public List<SubObject> SubObjects {get;set;}
}

public class SubObject {get;set;}
{
public string Id {get;set;}
public string Name {get;set;}
}

如何构造查询以返回Name.Contains("a")

中的SubObject列表

我觉得它应该是直截了当的,但我真的很挣扎。

3 个答案:

答案 0 :(得分:2)

简短的回答,你没有。 RavenDb中的文档是聚合根,您无法加载聚合根的一部分,只能加载整个根。因此,您可以获取包含Objects的所有Subobjects,其中包含'a'的名称,但您无法自行获取子对象。如果需要单独获取它们,请将SubObjects设置为自己的文档。

答案 1 :(得分:2)

在根对象上,您需要存储子对象的ID。然后,在加载根对象时,需要在查询中使用Raven Include()功能。这将把所有subObject文档拉入会话。然后,您可以加载子对象。这是我一直在做的一个例子:

这是一个根对象:

public class Application : EntityBase

Application具有CustomVariableGroup类型的子对象。所以我需要在对象中存储ID(这就是RavenDB将保存的内容)。

public List<string> CustomVariableGroupIds { get; set; }  // For RavenDB

实际的子对象仍然存储在根对象上,但不会以这种方式保存在Raven中:

[JsonIgnore]  //  We do not want RavenDB to serialize this.
public ObservableCollection<CustomVariableGroup> CustomVariableGroups

这就是设置,现在是Raven处理它的方式。 (忘掉ExecuteQuery()方法;这是我自己的,超出了这个问题的范围。)

这是获取根对象的调用。注意我们将ID拉入会话的Include():

public Application GetByName(string name)
{
    return ExecuteQuery<Application>(() =>
    {
        Application application = QuerySingleResultAndSetEtag(session =>
            session.Query<Application>()
            .Include(x => x.CustomVariableGroupIds)
            .Where(app => app.Name == name).FirstOrDefault())
            as Application;

        HydrateApplication(application);

        return application;
    });
}

以下是我们加载subObjects的方法:

public static void HydrateApplication(Application app)
{
    if (app == null) { throw new ArgumentNullException("app"); }
    if (app.CustomVariableGroupIds == null) { return; }

    app.CustomVariableGroups = new ObservableCollection<CustomVariableGroup>();

    foreach (string groupId in app.CustomVariableGroupIds)
    {                
        app.CustomVariableGroups.Add(QuerySingleResultAndSetEtag(session => session.Load<CustomVariableGroup>(groupId)) as CustomVariableGroup);
    }
}

最后,在保存根对象时,我确保保存子对象ID:

private static void SetCustomVariableGroupIds(Application application)
{
    application.CustomVariableGroupIds = new List<string>();

    if (application.CustomVariableGroups == null || application.CustomVariableGroups.Count < 1) { return; }

    foreach (CustomVariableGroup group in application.CustomVariableGroups)
    {
        application.CustomVariableGroupIds.Add(group.Id);
    }
}

希望有所帮助。这允许人们保持域模型“纯粹”IMO。实体可以保存对其他实体的引用,而不仅仅是其他实体的非规范化版本。

好的,并且实际回答你的问题......一旦你的文档被加载,你可以简单地使用LINQ来查询subObjects,因为现在它们实际上会在内存中。

答案 2 :(得分:1)

Session.Query<Object>.Where(x => x.SubObject.Any(a => a.Name.StartsWith("a"))).ToList();

我不确定Contains是否有效,但这应该让你开始。