【问题标题】:What's the most efficient way of reading relations out of a pouchdb database从 pouchdb 数据库中读取关系的最有效方法是什么
【发布时间】:2015-12-18 08:14:23
【问题描述】:

我在电子应用程序上使用 pouchDb。数据在传递给 pouchDb 之前存储在 postgres 数据库中。在某些情况下,不难弄清楚如何以文档方式构造数据。

我主要关心的是关系。例如:

我有数据类型 Projects 并且 Projects 有很多事件。现在我在每个事件上都有一个名为 project_id 的字段。因此,当我想获取 ID 为“project/1”的项目的事件时,我会这样做

_db.allDocs({
   include_docs: true,
   startkey: 'event',
   endkey: 'event\uffff'
}).then(function(response){
   filtered = _.filter(response['rows'], function(row){
      return row['doc']['project_id'] == 'project/1'
   });
   result = filtered.map(function(row){
      return row['doc']
   })
});

我听说allDocs 是性能最高的 API,但是,在这种情况下查看是否更方便?

另一方面,当我显示所有项目的列表时,每个项目都需要显示它拥有的事件数。在这种情况下,我似乎必须再次运行 allDocs,使用include_docs: false 才能计算项目的事件数。

有视图可以改善这种情况吗?

另一方面,我正在考虑在项目文档中创建一个包含所有事件 ID 的数组,以便我可以轻松计算它有多少事件。在这种情况下,我应该使用 allDocs 吗?有没有办法将一组 Ids 传递给 allDocs?或者在该数组上使用循环并为每个 id 调用 get(id) 会更好吗?

这种方式是否比第一种方式更高效?

谢谢!

【问题讨论】:

    标签: database couchdb pouchdb document-oriented-db


    【解决方案1】:

    好问题!在 PouchDB 中有很多方法可以处理关系。与许多 NoSQL 数据库一样,每个数据库都会在性能与便利性之间进行权衡。

    您描述的系统性能不是很好。基本上,您正在获取数据库中的每个事件 (O(n)),然后在内存中进行过滤。如果你有很多事件,那么n 会很大,这意味着它会非常非常慢。

    这里有几个选项。它们都比您当前的系统更好:

    1. Linked (aka joined) documents in map/reduce。 IE。在您的map 函数中,您将为每个事件emit() 项目_ids。这将为您在emit() 函数中作为key 放置的任何内容创建二级索引。
    2. relational-pouch,这是一个插件,它通过使用前缀 _ids 并运行 allDocs() 和 startkey 和 endkey 来工作。所以它会先使用allDocs() 来获取项目,然后再使用allDocs() 来获取该项目的事件。
    3. 完全独立的数据库,例如new PouchDB('projects') 和 new PouchDB('events')

    (大致按性能从最低到最高的顺序列出。)

    #1 比您描述的系统性能更高,尽管它仍然不是非常快,因为它需要创建二级索引,然后基本上会在二级索引数据库以及原始数据库(获取链接的文档)。所以基本上你在引擎盖下运行了三次allDocs()——其中一次是在你作为key发出的任何东西上,看起来你不需要它,所以它只会被浪费。

    #2 要好得多,因为它在后台运行两个快速的allDocs() 查询——一个用于获取项目,另一个用于获取事件。它也不需要创建二级索引;它可以使用免费的_id索引。

    #3 还需要两个allDocs() 调用。那么为什么它是最快的呢?好吧,有趣的是,这是因为 IndexedDB 如何在后台订购读/写操作。假设您正在写信给'projects' 和'events'。 IndexedDB 将做的是序列化这两个写入,因为它不能确定这两个不会修改相同的文档。 (不过,在读取方面,这两个查询在任何一种情况下都可以同时运行——至少在 Chrome 中。我相信 Firefox 实际上会序列化读取。)所以基本上如果你有两个完全独立的 PouchDB,代表两个完全独立的 IndexedDB ,则可以同时进行读取和写入。

    当然,在父子关系的情况下,不能提前知道子ID,所以无论如何都要先取父,再取子。所以在这种情况下,#2 和 #3 之间没有性能差异。

    在你的情况下,我想说最好的选择可能是#2。这是性能和便利性之间的一个很好的折衷,特别是因为 relational-pouch 插件已经为您完成了工作。

    【讨论】:

    • 对于案例 3,如果你做了 allDocs().then( () => allDocs().) 会同时运行吗?
    猜你喜欢
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多