2

我在电子应用程序上使用 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 吗?有没有办法将一组 Ids 传递给 allDocs?或者在该数组上使用循环并为每个 id 调用 get(id) 会更好吗?

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

谢谢!

4

1 回答 1

7

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

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

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

  1. map/reduce 中的链接(又名加入)文档。即在您的map功能中,您将为每个事件提供emit()项目_id。这会在您放在函数key中的任何内容上创建一个二级索引。emit()
  2. 关系袋,这是一个插件,它通过使用前缀_ids 并与allDocs()每个前缀一起运行。所以它会先获取项目,然后再获取该项目的事件。startkeyendkeyallDocs()allDocs()
  3. 完全独立的数据库,例如new PouchDB('projects')new PouchDB('events')

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

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

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

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

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

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

于 2015-12-18T00:14:23.753 回答