Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
couchdb中的唯一约束_Couchdb - Fatal编程技术网

couchdb中的唯一约束

couchdb中的唯一约束,couchdb,Couchdb,是否有实施独特约束的技术/建议?是的,我们可以创建唯一的密钥,但我们不能更改密钥和密钥,而且这种方法不适合复杂的验证(单独的唯一登录、单独的唯一电子邮件等) 例如,一个帐户应该有 独特的登录和电子邮件。导出密钥 从该字段将生成 不一致: key1: "Account-john@example.net-john", { email: "john@example.net", login: "john"} key2: "Account-mary@example.net-mary", { email:

是否有实施独特约束的技术/建议?是的,我们可以创建唯一的密钥,但我们不能更改密钥和密钥,而且这种方法不适合复杂的验证(单独的唯一登录、单独的唯一电子邮件等)

例如,一个帐户应该有 独特的登录和电子邮件。导出密钥 从该字段将生成 不一致:

key1: "Account-john@example.net-john", { email: "john@example.net", login: "john"}
key2: "Account-mary@example.net-mary", { email: "mary@example.net", login: "mary"}
看起来不错,但是:

key1: "Account-john@example.net-mary", { email: "john@example.net", login: "mary"}
key2: "Account-mary@example.net-mary", { email: "mary@example.net", login: "mary"}

哎呀,现在我们有两个登录名为“mary”的帐户,具体取决于。考虑多主复制的情况,可能有冲突的条目添加在每个主机内一致,但一旦复制它们就不一致。您可能只使用一台couchdb服务器,但一般来说,他们设计它时假设使用多主服务器,并且没有添加任何只在单个未复制服务器中正常工作的功能


如果您只关心单服务器的情况,那么您可以利用网络支持重建CouchJ,并在
validate\u doc\u update()
函数中执行http查询,该函数将对DB执行查询,查看电子邮件地址是否已被使用,如果已被使用,则更新失败。查看有关验证机制的更多详细信息。我不建议这样做,相反,我会在id字段中嵌入所有唯一性(直接或通过哈希),如果用户更改了任何影响的内容,则只需移动文档。

这是CouchDB中不太有趣的部分之一。我发现处理可以更改的唯一字段的最佳方法(如在您的用户示例中)是创建具有唯一值的“指针”文档作为键的一个组件,然后使用这些文档声明唯一值。这样做的重要部分是为主文档拥有一个可预测的密钥,然后在保存主文档之前保存唯一的字段声明文档(并允许密钥冲突阻止主文档保存)

给定具有唯一用户名和唯一电子邮件的用户,您的主要文档可能如下所示:

user-1234: { username: "kurt", email: "kurt@localhost" }
user-9876: { username: "petunia", email: "pie@crust.com" }
user-username-kurt: { primary_doc: "user-1234" }
user-email-kurt@localhost: { primary_doc: "user-1234" }
user-username-petunia: { primary_doc: "user-9876" }
user-email-pie@crust.com: { primary_doc: "user-9876" }
唯一的字段指针如下所示:

user-1234: { username: "kurt", email: "kurt@localhost" }
user-9876: { username: "petunia", email: "pie@crust.com" }
user-username-kurt: { primary_doc: "user-1234" }
user-email-kurt@localhost: { primary_doc: "user-1234" }
user-username-petunia: { primary_doc: "user-9876" }
user-email-pie@crust.com: { primary_doc: "user-9876" }
创建或更新用户将采取以下步骤:

  • 准备您的用户文档,必要时为其生成密钥
  • 为每个更改的唯一字段保存一个“指针”文档
  • 如果保存其中任何一个失败,请停止并修复错误
  • 保存主用户文档
  • 第三步需要一些思考。例如,您不想尝试为未更改的字段声明唯一值。你可以,但是你必须加入一些额外的逻辑来处理你为已经拥有该值的用户声明一个值的情况

    第三步将是一个好地方,让人们也接受旧的价值观。例如,如果一个用户“释放”了用户名kurt,我可以在验证新密钥不再使用后更新该特定文档以指向我的新密钥。另一种方法是在声明的唯一值发生更改时清除它们。真的,我不确定哪一个工作会少一些。在中保留过时的声明值对我来说最有意义

    这个解决方案的有趣之处在于,一旦创建了指针文档,您就不需要将它们用于任何事情。您可以像往常一样在用户文档上创建视图,并使用它们通过电子邮件或用户名进行查询


    此设置还允许您处理关系,而无需担心级联用户密钥。我不知道你的情况,但我的用户文档几乎被系统中的所有其他文档引用。更改用户密钥将是一个巨大的麻烦。

    核心答案

    为具有要保持唯一字段的文档构建POST/PUTs,如下所示:

  • 创建一个。在映射函数中,使用要强制唯一的字段作为键。价值可以是零。使用reduce函数获取每个键的计数。最好的方法(性能)是使用内置的reduce函数

  • 在将新文档放入/发布到数据库后,立即抓取返回的
    id
    rev
    GET/yourdb/\u design/yourapp/\u view/viewname?group=true&key=“value-of-your-unique-field-from-step-1”

  • 如果最后一次获取的结果给出的计数值不是1,那么您只需插入一个副本。立即删除/yourdb/id-from-step-2?rev=rev-from-step-2

  • 放松


  • 粗略示例

    假设您正在存储用户帐户,并且希望确保电子邮件地址是唯一的,但不希望将其作为文档id(无论出于何种原因)。如上所述,构建一个视图以快速检查电子邮件地址的唯一性。我们称之为电子邮件。它将有一个映射函数,可能与此类似

    function(doc) {  
      if(doc.type === 'account') {
        emit(doc.email, 1);
      }
    }
    
    只需将
    \u count
    作为reduce函数。如果您发出一个1像上面的
    \u sum
    也会起作用。如上所示,在您的文档上设置并检查
    类型
    字段只是一种惯例,但有时我觉得它很有用。如果您存储的只是用户帐户,那么您可能不需要它

    现在让我们假设我们正在插入这样一个文档

    POST /mydb/
    {
      "name": "Joe",
      "email": "joe@example.org"
    }
    
    CouchDB会用类似于

    {
      ok: true,
      id: 7c5c249481f311e3ad9ae13f952f2d55,
      rev: 1-442a0ec9af691a6b1690379996ccaba6
    }
    
    查看我们现在是否有多个joe@example.org在数据库中

    GET /mydb/_design/myapp/_view/emails/?group=true&key="joe@example.org"
    
    CouchDB会用类似于

    {
      rows: [
        {
          key: "joe@example.org",
          value: 1
        }
      ]
    }
    
    如果回复中的
    value
    不是
    1
    ,那么您可能只是插入了一封重复的电子邮件。因此,删除文档并返回一个错误,其中电子邮件地址必须是唯一的,类似于典型的SQL数据库响应,或者任何您想要的

    删除会像这样进行

    DELETE /mydb/7c5c249481f311e3ad9ae13f952f2d55?rev=1-442a0ec9af691a6b1690379996ccaba6
    

    简短讨论(如果您愿意)

    如果你来自一个好的老地方