簡體   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