繁体   English   中英

在CouchDB中使用JSON模式

[英]Work with JSON schema in CouchDB

我想问一下CouchDB中关于JSON原理图的好实践。 我现在使用纯CouchDB 1.6.1。 我没有任何couchapp框架处理它(我知道这很有用,但我担心它将来会有用)。

  • 在CouchDB中放置架构? 作为常规文件? 设计文件? 或者可能将它们存储为文件? 但是如果我要验证它们,尤其是validate_doc_update函数中的服务器端,它们应该存储在设计文档中。

  • 在CouchDB和Client(Web浏览器)中是否有任何库(JavaScript最好)? 我的库可以生成JSON并自动验证它们吗?

  • 我考虑如何将数据发送到客户端,将它们存储在输入标签中,然后以某种方式收集并发送到serwer。 也许将输入id设置为字段的路径,例如:

    {“地址”:{“街道”:“xxx”,“Nr”:“33”}}

在这种情况下输入可能有id =“Adress。”Street“,但我不知道这是一个很好的解决方案。我应该从服务器发送模式并使用这个模式构建JSON对象,但不知道如何(如果所有字段都在JSON具有唯一的名称 - 包括层次结构。

在探索CouchDB在数据表单用例中的潜在优势时,您会问我多年来所遇到的同样问题。

最初,我希望找到一种方法,该方法基于相同的JSON模式定义和验证代码(服务器端和客户端端)实现数据验证。 事实证明,它不仅可能而且还存在一些额外的优点。

在CouchDB中放置架构? 作为常规文件? 设计文件? 或者可能将它们存储为文件? 但是如果我要验证它们,尤其是validate_doc_update函数中的服务器端,它们应该存储在设计文档中。

你是对的。 设计doc(ddoc)还包括validate_doc_update函数,用于在doc更新之前执行验证,这是放置schemata的最常见位置。 this在validate_doc_update函数中是ddoc本身 - ddoc中包含的所有内容都可以从验证码。

我已经开始将schemata作为JSON对象存储在我的通用库属性/文件夹中,用于commonjs模块,例如lib/schemata.json 我的文档的type属性指定了doc更新验证应该获取的模式的键,例如type: 'adr' - > lib/schemata/adr 模式也可以引用每个属性的其他模式 - 无论嵌套属性是什么类型,递归验证函数都遍历到任何属性的末尾。 它在第一个项目中运作良好。

{
  "person": {
    "name": "/type/name",
    "adr": "/type/adr",
    ...
  },
  "name": {
    "forname": {
      "minlenght": 2,
      "maxlength": 42,
      ...
    },
    "surname": {
      ...
    }
  },
  "adr": {
    ...
  }
}

但后来我想在另一个项目中使用该模式的子集。 简单地复制它并添加/删除一些模式本来是太短视的想法。 如果像地址这样的通用模式有错误并需要在每个使用它的项目中更新怎么办?

此时我的架构存储在存储库中的一个文件中(我使用erica作为ddocs的上传工具)。 然后我意识到,当我将每个模式存储在一个单独的文件中时,例如adr.jsongeo.jsontel.json等,它会在服务器ddoc中产生与单个文件方法相同的JSON结构。 但它更适合源代码管理。 不仅较小的文件导致较少的合并冲突和更清晰的提交历史记录 - 还启用了通过子存储库(子模块)的模式依赖关系管理。

另一个想法是使用CouchDB本身作为模式存储和管理的地方。 但正如您自己提到的那样 - 必须可以在validate_doc_update函数中访问模式。 首先,我尝试了一种使用更新处理程序的方法 - 每个doc更新都必须传递一个验证更新处理程序,它自己从CouchDB中获取正确的模式:

POST /_design/validator/_update/doctype/person

function (schema, req) {
   ... //validate req.body against schema "person"
  return [req.body, {code: 202, headers: ...}]
}

但是这种方法不适用于嵌套模式。 更糟糕的是 - 为了在没有通过处理程序验证的情况下阻止文档更新,我不得不在CouchDB前面使用代理来隐藏直接内置的doc更新路径(例如POST到/ / doc / _id)。 我没有找到一种在validate_doc_update函数中检测更新处理程序是否涉及之前的方法(也许其他人有?我很乐意阅读这样的解决方案。)。

在那次调查中,同一架构的不同版本的问题出现在我的雷达上。 我应该如何管理? 所有相同类型的文档必须对相同的模式版本有效(在几乎每个模式版本更改之前,还需要进行数据库范围的数据迁移)? type属性是否还包含版本号? 等等

可是等等! 如果文档的架构附加到文档本身怎么办? 它:

  • 将为每个doc提供doc内容的兼容版本
  • 可以在validate_doc_update函数中访问(在oldDoc
  • 可以在没有管理员访问权限的情况下进行复制(因为您需要ddoc更新)
  • 将包含在客户端文档请求的每个响应中

这听起来非常有趣,直到现在我感觉像CouchDB-ish这样的方法。 说清楚 - 文档的架构附加到文档本身 - 意味着将它存储在doc的属性中。 作为附件的存储和作为doc结构的模式本身的使用都不成功。

这种方法最敏感的时刻是文档的CRUD生命周期中的C (创建)。 有许多不同的解决方案可以确保附加的模式是“正确和可接受的”。 但这取决于您在特定项目中对该术语的定义。

在CouchDB和Client(Web浏览器)中是否有任何库(JavaScript最好)? 我的库可以生成JSON并自动验证它们吗?

我开始使用流行的JQuery Validation插件实现 我可以使用架构作为配置,并自动获得整洁的客户端验证。 在服务器端,我已将验证函数解压缩为commonjs模块。 我希望以后能够找到一种模块化的代码管理方法来防止代码重复。

事实证明,大多数现有的验证框架在模式匹配和单属性验证方面都非常出色,但不能在同一文档中验证依赖值。 模式定义要求通常也是专有的。 对我来说,选择正确的模式定义的经验法则是:更喜欢自己实现的标准化定义(jsonschema.org,微数据,rdfa,hcard等)。 如果您保留结构和属性名称,那么您将需要更少的文档,更少的转换,有时您也可以自动获得用户使用的外国软件(例如日历,地址簿等)的兼容性。 如果您想为您的文档实现HTML演示文稿,您已准备好以语义Web-ish和SEO-zed方式进行。

最后 - 不希望听起来傲慢 - 编写模式验证实现并不困难。 也许你想阅读JQuery Validation Plugin的源代码 - 我相信你会发现像我一样令人惊讶的可理解。 在前端框架的流失率增加的时候,它可能是拥有自己的验证功能的最具前瞻性的方式。 此外,我相信您应该100%了解验证实现 - 它是您的应用程序的关键部分。 如果您了解外部实现 - 您也可以自己编写库。

好。 这是一个很好的答案。 抱歉。 如果有人将其读到最后并希望通过示例源代码查看详细信息 - upvote,我将编写博客文章并将URI附加为注释。

我会告诉你,我是如何实现它的。

  1. 我有一个每个文档类型的数据库,它允许我为每个数据库实现一个模式。

  2. 在每个数据库上,我有一个_design/schema ddoc,它包含一个schema和validate_doc_update函数来验证它。

  3. 我正在使用Tiny Validator(适用于v4 JSON Schema) ,我将其包含在_design/schema ddoc中。


_design/schema ddoc如下所示:

{
  "_id": "_design/schema",
  "libs": {
    "tv4": // Code from https://raw.githubusercontent.com/geraintluff/tv4/master/tv4.min.js
  },
  "validate_doc_update": "..."
  "schema": {
    "title": "Blog",
    "description": "A document containing a single blog post.",
    "type": "object",
    "required": ["title", "body"],
    "properties": {
      "_id": {
        "type": "string"
      },
      "_rev": {
        "type": "string"
      },
      "title": {
        "type": "string"
      },
      "body": {
        "type": "string"
      }
    }
  }
}

validate_doc_update函数如下所示:

function(newDoc) {
  if (newDoc['_deleted']) return;

  var tv4 = require('libs/tv4');

  if (!tv4.validate(newDoc, this.schema)) {
    throw({forbidden: tv4.error.message + ' -> ' + tv4.error.dataPath});
  }
}

希望这可以帮助。

也许最好的选择是使用json-schema 你有很多语言的实现 我已经在javascript中成功使用了tv4

为了与couch db集成,我认为最好的选择是定义验证函数并使用json-schema javascript验证器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM