我一直在研究Nosql(尤其是RavenDB),我仍然不确定接近以下方法的最佳方法:
我有两个简单的对象,'用户'和'事件'。用户可以输入许多事件,并且许多用户可以输入事件 - 标准的多对多关系。我正试图摆脱关系数据库的思维模式!
以下是我要针对数据库运行的查询/操作:
所以从我读过的内容来看,我有几个选择:
这对我来说似乎最符合逻辑,但它感觉相当'关系数据库'方法?
似乎是明智的,但是这不会使双向查询变得困难吗?
非常感谢,
Dan C
答案 0 :(得分:2)
实际上,RavenDB非常适合。要正确地做到这一点,问问自己模型中的主要实体是什么?其中每一个都是RavenDB中的文档类型。
因此,在您的方案中,您有Event
和User
。然后,Event
可以包含User
ID列表,您可以轻松地对其进行索引和查询。有更多的方法可以做到这一点,我实际上discussed this in my blog some time in the past可能会出现一些进一步的考虑因素。
唯一的非平凡位可能是回答查询的索引,例如"用户尚未输入的所有事件",但这也很容易完成:
public class Events_Registrations : AbstractIndexCreationTask<Event>
{
public Events_Registrations()
{
Map = events => from e in events
select new { EventId = e.Id, UserId = e.Registrations.SelectMany(x => x.UserId) });
}
}
一旦你有这样的索引,你可以进行如下的查询,以获得指定用户没有注册的所有事件:
var events = RavenSession.Advanced.LuceneQuery<Event, Events_Registrations>()
.Where("EventId:*")
.AndAlso()
.Not
.WhereEquals("UserId", userId).ToList();
然后处理过期事件等事情很容易。绝对不会在User对象中对事件数据进行非规范化处理,它会让你的生活充满生机。
虽然缺少一些数据 - 例如每个事件允许注册的数量。如果有太多,您可能想要将其从实际的Event
对象中分离出来,或者在您提及时恢复为预订对象。我在我的RavenDB in Action一书中详细讨论了这个问题(无耻的插件,我知道,但实际上这里讨论的时间太长了。)
答案 1 :(得分:0)
不知道确切的要求和预期用途会使设计变得有点渺茫。也就是说,我会说选择2.这是最合乎逻辑的结构。
然后创建索引以支持您需要的其他类型的视图。您没有在问题中指定它,但您可能希望查看用户输入的单个事件。这是通过索引完成的。
“删除事件”。你真的想要删除它们吗?我想你希望能够列出所有“活跃”事件。对?如果是这样,也可以通过索引轻松完成。
我会说在设计实体时使用“Aggregate Roots”的思维模式,并使用索引来支持您的查询。另请注意,RavenDB索引与RDBMS中的索引不同。您可以在某种程度上将RavenDB索引视为RDBMS“View”。
还知道有不同类型的RavenDB索引。这些类型在客户端编程接口中并不十分清晰(我发现它是Raven中的一个大缺陷,它仍然让我感到困惑)。浏览工作室中的索引是理解索引中数据的好方法。