我在电子应用程序上使用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
以便计算项目所具有的事件数.
有观点会改善这种情况吗?
另一方面,我正在考虑在Project文档中创建一个包含所有事件ID的数组,以便我可以轻松计算它有多少事件.在这种情况下,我应该使用allDocs吗?有没有办法将ID数组传递给allDocs?或者更好的是在该数组上使用循环并为每个id调用get(id)?
这种方式比第一种更有效吗?
谢谢!
好问题!有许多方法可以处理PouchDB中的关系.和许多NoSQL数据库一样,每个数据库都会为您提供性能与便利性的权衡.
您描述的系统并不是非常高效.基本上,您将获取数据库中的每个事件(O(n)
),然后在内存中进行过滤.如果你有很多事件,那么n
会很大,这意味着它会非常慢.
你有几个选择.所有这些都优于您当前的系统:
map/reduce中的链接(也称为已加入)文档.即在你的map
功能中,你将为每个事件做emit()
项目_id
.这会key
在emit()
函数中创建一个二级索引.
relational-pouch,这是一个插件,通过使用前缀_id
s并allDocs()
使用startkey
和endkey
为每个运行.所以它会做一个allDocs()
来获取项目,然后是第二个allDocs()
来获取该项目的事件.
完全独立的数据库,例如new PouchDB('projects')
和new PouchDB('events')
(粗略地说,这些是按性能最差的顺序列出的.)
#1比你描述的系统性能更高,虽然它仍然不是非常快,因为它需要创建一个二级索引,然后在它之后基本上会allDocs()
在二级索引数据库和原始数据库上执行(以获取链接文档).所以基本上你allDocs()
在引擎盖下运行了三次 - 其中一次是在你发出的任何东西上key
,它看起来你不需要,所以它只会浪费.
#2要好得多,因为它会运行两个快速allDocs()
查询 - 一个用于获取项目,另一个用于获取事件.它也不需要创建二级索引; 它可以使用免费_id
索引.
#3还需要两个allDocs()
电话.那为什么它最快?好吧,有趣的是,这是因为IndexedDB如何在引擎盖下命令读/写操作.假设你写的是'projects'
和'events'
.IndexedDB将做的是序列化这两个写入,因为它不能确定这两个写入不会修改相同的文档.(但就读取而言,这两个查询可以在任何一种情况下同时运行 - 至少在Chrome中.我相信Firefox实际上会对读取进行序列化.)所以基本上如果你有两个完全独立的PouchDB,代表两个完全独立的IndexedDBs ,然后读取和写入都可以同时完成.
当然,在父子关系的情况下,您无法提前知道子ID,因此您必须先获取父级,然后获取子级.因此,在这种情况下,#2和#3之间没有性能差异.
在你的情况下,我会说最好的选择可能是#2.这是性能和便利之间的一个很好的折衷,特别是因为relational-pouch
插件已经为你工作了.