You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RavenDB中单次存储关联文档至不同集合并一次性查询?

核心问题概要

是否可以实现以下操作:

  • 通过一次RavenDB的Store/StoreAsync调用,将带有关联关系(Tags)的文档(Article)存储到不同的集合中?
  • 随后通过一次查询获取父文档(Article)及其关联文档(Tags),无需单独包含/加载Tags?
问题说明

目前在RavenDB中,存储带有关联关系的数据到不同集合的常规方式是分别存储各文档。读取数据时,需要使用Include指定关联文档,再调用Load获取。

我想知道是否有办法简化这一流程,实现Articles和关联Tags的一键存储与查询。

我整理了两种实现思路:一种是期望但无法工作的方案,另一种是可行但繁琐的方案,通过对比便于理解。

示例分为以下步骤:

  • POCO类定义
  • 数据存储
  • 索引定义
  • 索引查询

POCO类定义

期望但无法工作的实现

namespace Articles
{
    public class ArticlePersistance
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public List<TagPersistance> Tags { get; set; } // 这里直接引用TagPersistance
    }

    [DearRavenDBStoreToSeparateCollectionPlease] // 该特性不存在
    public class TagPersistance
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }
}

可行的实现

namespace Articles
{
    public class ArticlePersistance
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public List<string> Tags { get; set; } // 这里用字符串存储ID
    }

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

数据存储

期望但无法工作的实现

通过一次StoreAsync调用,将ArticlePersistance和TagPersistance存储到各自集合中。但实际这样会把Article和Tags存入同一个集合。

var tag = new TagPersistance() { Name = "Tag1" };
var article = new ArticlePersistance()
{
    Title = "aaa",
    Tags = new List<TagPersistance> { tag } // 直接嵌入完整Tag对象
};
await session.StoreAsync(article); // 仅调用一次StoreAsync
await session.SaveChangesAsync();

可行的实现

分别存储Article和Tags:

var tag = new TagPersistance() { Name = "Tag1" };
await session.StoreAsync(tag); // 单独存储Tag

var article = new ArticlePersistance()
{
    Title = "aaa",
    Tags = new List<string> { tag.Id } // 仅嵌入Tag的ID
};
await session.StoreAsync(article);

await session.SaveChangesAsync();

索引定义

期望但无法工作的实现

基于ArticlePersistance创建索引,存储完整的Tag对象:

public class Articles_Test : AbstractIndexCreationTask<ArticlePersistance>
{
    public Articles_Test()
    {
        Map = articles => 
               from article in articles
               let tags = article.Tags.Select(t => LoadDocument<TagPersistance>(t)) // 加载关联的Tags
               select new
               {
                   Title = article.Title,
                   Tags = tags // 存储完整的Tag对象
               };
    }
}

可行的实现

仅存储Tag名称而非完整Tag对象的索引:

public class Articles_Test : AbstractIndexCreationTask<ArticlePersistance>
{
    public Articles_Test()
    {
        Map = articles => 
               from article in articles
               let tags = article.Tags.Select(t => LoadDocument<TagPersistance>(t)) // 加载关联的Tags
               select new
               {
                   Title = article.Title,
                   Tags = tags.Select(t => t.Name) // 仅存储Tag名称
               };
    }
}

索引查询

期望但无法工作的实现

查询索引并一次性获取包含Tags的Article:

// 此代码无法正常工作
var article = await session
    .Query<ArticlePersistance, Articles_Test>()
    .Where(a => a.Title == "aaa")
    .ToListAsync();

可行的实现

该方案可行但繁琐,需要手动处理Article和Tags的关联:

var article = await session
    .Query<ArticlePersistance, Articles_Test>()
    .Where(a => a.Title == "aaa")
    .Include(t => t.Tags) // 包含关联的Tags
    .ToListAsync();
// 单独查询Tags
var tags = await session.LoadAsync<TagPersistance>(article.SelectMany(a => a.Tags));

内容的提问来源于stack exchange,提问作者Simon Lang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:01:17