Database design 如何存储查询的RavenDB文档计数

Database design 如何存储查询的RavenDB文档计数,database-design,indexing,mapreduce,ravendb,cqrs,Database Design,Indexing,Mapreduce,Ravendb,Cqrs,我在RavenDB中有一个文档集合,客户机应用程序围绕它执行相对直接的CRUD。有一个简单的仅映射索引用于查询集合 我现在必须向应用程序添加一个功能,该功能将显示在查询中检索单个文档的次数,即应用程序“提供”的次数。这样,当您通过应用程序查看单个文档时,您可以看到该文档已送达的次数。还需要一个“重置”按钮,将计数设置回零,然后允许计数继续增加 为了降低应用程序接口的复杂性,故意将需求保持在原始状态。已经讨论了日期范围报告的选项,认为没有必要 某些上下文:某些文档的增量服务计数可能每天超过1000

我在RavenDB中有一个文档集合,客户机应用程序围绕它执行相对直接的CRUD。有一个简单的仅映射索引用于查询集合

我现在必须向应用程序添加一个功能,该功能将显示在查询中检索单个文档的次数,即应用程序“提供”的次数。这样,当您通过应用程序查看单个文档时,您可以看到该文档已送达的次数。还需要一个“重置”按钮,将计数设置回零,然后允许计数继续增加

为了降低应用程序接口的复杂性,故意将需求保持在原始状态。已经讨论了日期范围报告的选项,认为没有必要

某些上下文:某些文档的增量服务计数可能每天超过10000。预计每周都会“重置”送达的文件数量。我应该能够在查询操作之外,以CQRS方式异步实现对数据库的增量写入

我可以想出三种方法,想知道最好的选择是什么

  • 向document对象添加integer Count属性,当随后调用递增对象时,该属性将在每个对象上递增。这将使文档大小保持较低

  • 向当前日期的文档对象添加一个列表属性,类似于选项1,该属性将附加到每个对象上。如果以后需要基于日期的报告,但文档可能会变得非常大,这会很有用吗

  • 添加一个单独的“柜台”文件集合,其中包括送达的文件id和送达的日期时间。我推测这将获得map/reduce索引的好处

  • 还有几个早期的后续问题

    • 有没有一种面向方面的方法可以通过RavenDB实现这一点
    • 使用更新(选项1+2)而不是插入(选项3)是否有任何性能优势,反之亦然

    感谢您的回答和阅读

    使用RavenDB实现这一点的面向方面的方法是使用。您可以将检索计数存储在文档元数据中。这将是性能最好的解决方案,因为不需要有关单个检索的信息

    更新

    正如maxbeaudoin所指出的,元数据是读取计数器的合适位置,因为它是关于数据的数据。此外,由于元数据与文档一起存储,因此它的性能也会很好。描述如何在RavenDB中使用元数据

    更新2


    如果只存储计数,那么元数据是性能和实用性的最佳选择。如果您需要存储每个视图事件,并且您预计每个文档可能会有数千个视图事件,那么我会将视图事件存储在单独的文档中,而不是存储在同一文档或文档元数据中。元数据只是键值对的集合,并不适用于大型集合。不存储在同一文档中的原因是,您必须更改文档模型以包含视图事件,这将污染您的模型,而且正如您所指出的,检索具有10K视图事件的文档将导致IO增加并导致性能问题。可以使用投影仅检索特定的文档字段,但不会跟踪返回的文档的更改。考虑到这个问题,我建议您重新考虑,除非您绝对需要,否则不要存储单个读取事件。

    也许我在这方面做得太离谱了,但您为什么要每天从数据库中实际加载此文档10k次呢?使用一些输出缓存可能会更好

    Raven缓存也将对您有利。我必须承认,如果客户端发生缓存命中,我不确定服务器上是否仍会触发读取触发器。如果你真的走了一条触发器路径,我会先验证这一点

    也许最好在客户端设置一个计数器。即使在缓存命中并且不接触raven时,也可以增加计数器。然后,您可以定期将计数器刷新回服务器,以更新文档本身或单独的stats文档中的count属性

    这对性能确实有帮助。假设您在5分钟内观看了50次。为什么每次增加1,只是每5分钟增加50。好吧,不完全是50,但不管你在这段时间在前端计量多少。这甚至可以扩展到多个服务器,如果您只是将新计数添加到现有计数,则可以通过raven的修补API应用更改

    更新

    我举了一个可能对你有帮助的例子。除了一些定期出现的计时器之外,它在客户端提供了您所需的一切。希望这值得你的赏金

    公共类计数器
    {
    //使用多线程单例模式
    //看http://msdn.microsoft.com/en-us/library/ff650316.aspx
    专用计数器(){}
    私有静态易失性计数器_实例;
    私有静态只读对象SyncRoot=新对象();
    公共静态反实例
    {
    得到
    {
    如果(_实例!=null)
    返回_实例;
    锁定(同步根)
    {
    if(_instance==null)
    _实例=新计数器();
    }
    返回_实例;
    }
    }
    私有只读ConcurrentDictionary\u readCounts=
    新的ConcurrentDictionary();
    公共无效增量(字符串documentId)
    {
    _AddOrUpdate(documentId,k=>1,(k,v)=>v+1);
    }
    公共长读取器和设置(字符串d