我在RavenDB中有以下实体集合:
public class EntityA
{
public string Id { get; set; }
public string Name { get; set; }
public string[] Tags { get; set; }
}
public class EntityB
{
public string Id { get; set; }
public string Name { get; set; }
public string[] Tags { get; set; }
}
唯一共享的是Tags
集合:EntityA
中可能存在EntityB
的标记,因此它们可能相交。
如何检索与EntityA
交叉标记的每个EntityB
,其中Name
EntityB
属性等于给定值?
答案 0 :(得分:2)
嗯,这很难。要做到这一点,你需要两个级别的减少 - 一个通过标记来扩展你的结果,另一个通过id来折叠它。 Raven没有一种简单的方法可以做到这一点。
你可以使用Transform来伪造它。唯一的问题是您的结果集中会有skipped items,因此请务必了解how to deal with those。
public class TestIndex : AbstractMultiMapIndexCreationTask<TestIndex.Result>
{
public class Result
{
public string[] Ids { get; set; }
public string Name { get; set; }
public string Tag { get; set; }
}
public TestIndex()
{
AddMap<EntityA>(entities => from a in entities
from tag in a.Tags.DefaultIfEmpty("_")
select new
{
Ids = new[] { a.Id },
Name = (string) null,
Tag = tag
});
AddMap<EntityB>(entities => from b in entities
from tag in b.Tags
select new
{
Ids = new string[0],
b.Name,
Tag = tag
});
Reduce = results => from result in results
group result by result.Tag
into g
select new
{
Ids = g.SelectMany(x => x.Ids),
g.First(x => x.Name != null).Name,
Tag = g.Key
};
TransformResults = (database, results) =>
results.SelectMany(x => x.Ids)
.Distinct()
.Select(x => database.Load<EntityA>(x));
}
}
另请参阅完整单元测试here。
还有另一种方法,但我还没有测试过它。那就是使用Indexed Properties Bundle进行第一次传递,然后将这些结果映射到第二次传递。我一般都在尝试这个,如果有效,我会用结果更新这个答案。