从 pouchdb 数据库中读取关系的最有效方法是什么

What's the most efficient way of reading relations out of a pouchdb database

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

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

我的数据类型是项目,项目有很多事件。现在我在每个事件上都有一个名为 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 吗?有没有办法将一组 ID 传递给 allDocs?或者在该数组上使用循环并为每个 id 调用 get(id) 会更好吗?

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

谢谢!

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

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

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

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

(粗略地说,这些是按性能从最低到最高的顺序列出的。)

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

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

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

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

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