您问的问题是我多年来探索在数据表单使用情况下CouchDB潜在优势时遇到的同样的问题。
最初,我的希望是找到一种方法,使基于相同的JSON模式定义和验证代码-服务器端和客户端的数据验证成为可能。结果证明,这不仅是可能的,而且还存在一些额外的优势。
在CouchDB中放置模式的位置?作为常规文档?设计文档?或者可能将它们存储为文件?但是如果我要验证它们,特别是在validate_doc_update函数中进行服务器端验证,它们应该存储在设计文档中。
您是正确的。设计文档(ddoc)也包括validate_doc_update函数以在文档更新之前执行验证,是放置模式的最常见位置。 validate_doc_update函数中的“this”是ddoc本身-可以从验证代码访问ddoc中包含的所有内容。
我已经开始将模式以JSON对象的形式存储在我的通用库属性/文件夹中,例如commonjs模块的
lib/schemata.json
。我的文档的
type
属性指定了文档更新验证应该获取的模式的键,例如
type: 'adr'
->
lib/schemata/adr
。一个模式也可以根据属性引用其他模式 - 递归验证函数已经遍历到任何属性的末尾,无论嵌套属性来自什么类型。这在第一个项目中运行良好。
{
"person": {
"name": "/type/name",
"adr": "/type/adr",
...
},
"name": {
"forname": {
"minlenght": 2,
"maxlength": 42,
...
},
"surname": {
...
}
},
"adr": {
...
}
}
但是我想在另一个项目中使用该模式的子集。简单地复制它并添加/删除一些模式是短视的思考方式。如果像地址这样的通用架构存在错误并且需要在使用它的每个项目中进行更新呢?
此时,我的模式存储在仓库中的一个文件中(我使用
erica作为ddocs的上传工具)。然后我意识到,当我将每个模式存储在单独的文件中,例如
adr.json
、
geo.json
、
tel.json
等,它会产生与单文件方法相同的JSON结构在服务器ddoc中。但它更适合源代码管理。不仅较小的文件导致较少的合并冲突和更清晰的提交历史,而且通过子仓库(子模块)实现了模式依赖项管理。
另一个想法是将CouchDB本身用作模式存储和管理位置。但正如您自己提到的那样 - 模式必须在validate_doc_update函数中可访问。首先,我尝试了一种更新处理程序的方法 - 每个文档更新都必须通过验证更新处理程序,该处理程序自己从CouchDB中获取正确的模式:
POST /_design/validator/_update/doctype/person
function (schema, req) {
...
return [req.body, {code: 202, headers: ...}]
}
但这种方法在嵌套模式下效果不佳。更糟糕的是,为了防止未经处理程序验证的文档更新,我不得不在CouchDB前面使用代理来隐藏直接内置的文档更新路径(例如POST到/the/doc/_id)。我没有找到一种方法来检测validate_doc_update函数是否在更新处理程序之前被涉及(也许有人有?我很高兴阅读这样的解决方案)。
在调查过程中,同一模式的不同版本问题出现在我的雷达上。我该如何管理它?必须所有相同类型的文档都有效地针对同一模式版本(这意味着需要在几乎每个模式版本更改之前进行全局数据迁移吗?)?类型属性是否也应包括版本号?等等。
但等等!如果文档的模式附加到文档本身呢?它:
- 将为每个文档提供兼容的版本
per doc
- 可以在validate_doc_update函数中访问(在
oldDoc
中)
- 可以在没有管理员访问权限的情况下复制(因为您需要ddoc更新)
- 将包含在客户端文档请求的每个响应中
这听起来非常有趣,也感觉像是目前最符合CouchDB的方法。明确地说,文档的结构模式附加在文档本身上,意味着将其存储在文档的属性中。无论是作为附件存储还是使用模式本身作为文档结构都没有成功。
该方法最敏感的时刻是文档CRUD生命周期中的C(创建)。有许多不同的解决方案可想而知,以确保所附加的模式“正确且可接受”。但这取决于您在特定项目中对这些术语的定义。
是否有库(最好是JavaScript)适用于CouchDB和客户端(Web浏览器)?我可以使用该库生成JSON并自动验证吗?
我开始使用流行的
JQuery Validation插件进行实现。我可以将模式用作配置,并自动获得整洁的客户端验证。在服务器端,我已经将验证函数提取为commonjs模块。我希望以后能找到一种模块化的代码管理方式,以避免代码重复。
现有的大多数验证框架在模式匹配和单属性验证方面非常出色,但不能够对同一文档中的相关值进行验证。此外,模式定义要求通常过于专有。对我来说,选择正确的模式定义的经验法则是:优先选择标准化定义(jsonschema.org、microdata、rdfa、hcard等),而不是自己实现。如果保留结构和属性名称,您将需要更少的文档、更少的转换,并且有时会自动与用户使用的外部软件(例如日历、地址簿等)兼容。如果您想为文档实现HTML演示文稿,那么您可以以语义Web和SEO方式做好准备。
最后,不想显得自大,编写模式验证实现并不困难。也许您想阅读JQuery Validation插件的源代码,我相信您会像我一样感到惊人的易懂。在前端框架的更新速度不断加快的时代,拥有自己的验证函数可能是最具未来性的方式。此外,我认为您应该对验证实现有100%的理解-这是应用程序的关键部分。如果您理解了外部实现,也可以自己编写库。
好的,这是一个很长的回答。抱歉。如果有人看完并想看到详细的实例源代码 - 给我点赞,我会写一篇博客文章并将 URI 附加为评论。