在过去的几年里,我一直在从事出版行业中使用NoSQL数据库的项目。作为一个程序员,作为一个从设计SQL数据库起家的人,我努力做到DRY。
在以文档为中心的数据库中,DRY似乎是被回避的东西,它甚至可能对性能和可伸缩性有害。当然,这是我的同事们的看法,他们与一些NoSQL供应商合作过,甚至为一些NoSQL供应商工作过。他们应该知道。
尽管如此,我还是很难做出精神上的飞跃,因为我发现很难接受DRY和NoSQL是不相容的。生活中有太多的事情开始于一种过分的推动,然后以最有效的妥协来解决。
数据经常重复,我一直看到完整性问题。我对程序员和高级管理人员的态度是拥抱它,拥抱它的生命。消费服务必须处理它,否则这是上游团队的问题。
我想知道为什么文档不是由许多小的子文档组成,并被引用,拼接在一起,就像一个视图,我猜。
"打印"到每个文档中的数据只能通过编写自定义的"查找替换"来更新,就像必须跨tb的操作一样。因此,这些特性增加了成本,并且对敏捷故事没有明确的需求,因此不会被构建。数据变得更加不一致
将文档分解成子文档的问题是,本机数据库搜索停止工作,因为它不知道文档-子文档的关系。因此,搜索必须是一个自定义过程,搜索子文档,然后整理它们链接到的主文档的外键。
是否有一个中间地带,或者真的是接受权衡的情况?关于这个问题的讨论并不多。
《路加福音》不确定您在哪个平台上,但是您是否看过在DB和客户端之间放置一层?
举个例子,我喜欢feathersjs的架构,它允许你在DB查询之前/之后运行钩子。在文档和子文档上下文中,查看包含的钩子populate和dePopulate。
下面是1:1关系的文档示例:
// users like { _id: '111', name: 'John', roleId: '555' }
// roles like { _id: '555', permissions: ['foo', bar'] }
import { populate } from 'feathers-hooks-common';
const userRoleSchema = {
include: {
service: 'roles',
nameAs: 'role',
parentField: 'roleId',
childField: '_id'
}
};
app.service('users').hooks({
after: {
all: populate({ schema: userRoleSchema })
}
});
// result like
// { _id: '111', name: 'John', roleId: '555',
// role: { _id: '555', permissions: ['foo', bar'] } }
PS: feathers支持多种数据库,也支持SQL数据库