CouchDB索引连接文档之间的关联

6
我有以下文件:
{ _id: "123", type: "project", worksite_id: "worksite_1" }
{ _id: "456", type: "document", project_id: "123" }
{ _id: "789", type: "signature", document_id: "456" }

我的目标是运行一个查询并最终筛选所有与 worksite_id: worksite_1 有联系的文档进行复制。
例如:
  1. 因为这个项目有我正在寻找的工地
  2. 文档中有该项目
  3. 签名中有该文档
如果我想要来自那个工地的所有内容,我应该能够检索到所有这些文档。
通常情况下,我只需将 type:documenttype:signature 添加一个 worksite_id。然而,由于各种原因,项目中的工地可能会更改。
我想知道是否有一种方法可以创建索引或做一些我没有考虑到的事情来显示这些相似之处。 这篇文章感觉走在正确的道路上,但解释将文档放在其他文档中,而我只想让它们分开。

你有没有考虑使用 relational-pouch - Martin Bramwell
1
@MartinBramwell 我相信我需要创建一个视图/过滤器来完成我需要使用复制进行的操作。 - bryan
2个回答

2

一个映射函数一次只考虑一个文档,因此除非该文档知道其他文档,否则无法将它们链接在一起。从SQL术语上来说,您的结构意味着三个表的连接。

使用您的结构,您最好只能得到两个请求的解决方案。您可以创建一个仅显示已签署文件的视图:

function (doc) {
  if (doc && doc.type && doc.type === "signature" && doc.document_id) {
    emit(doc.document_id, {_id: doc.document_id})
  }
}

使用相同的技巧将项目链接到文档,但你无法将三个都链接起来。


0

我认为我有你需要的。

以下是一些数据:

{
  "docs": [
    {
        "_id": "123",
        "type": "project",
        "code": "p001"
    },
    {
        "_id": "1234",
        "type": "worksitelog",
        "documents": [
          {
            "timestamp": "20180921091501",
            "project_id": "123",
            "document_id": "457",
            "signature_id": "789"
          },
          {
            "timestamp": "20180921091502",
            "project_id": "123",
            "document_id": "457",
            "signature_id": "791"
          },
          {
            "timestamp": "20180921091502",
            "project_id": "123",
            "document_id": "458",
            "signature_id": "791"
          },
          {
            "timestamp": "20180921091502",
            "project_id": "123",
            "document_id": "456",
            "signature_id": "790"
          }
        ],
        "worksite_id": "worksite_2"
    },
    {
        "_id": "1235",
        "type": "worksitelog",
        "documents": [
          {
            "timestamp": "20180913101502",
            "project_id": "125",
            "document_id": "459",
            "signature_id": "790"
          }
        ],
        "worksite_id": "worksite_1"
    },
    {
        "_id": "124",
        "type": "project",
        "code": "p002"
    },
    {
        "_id": "125",
        "type": "project",
        "code": "p003"
    },
    {
        "_id": "456",
        "type": "document",
        "code": "d001",
        "project_id": "123",
        "worksite_id": "worksite_2"
    },
    {
        "_id": "457",
        "type": "document",
        "code": "d002",
        "project_id": "123",
        "worksite_id": "worksite_2"
    },
    {
        "_id": "458",
        "type": "document",
        "code": "d003",
        "project_id": "123",
        "worksite_id": "worksite_2"
    },
    {
        "_id": "459",
        "type": "document",
        "code": "d001",
        "project_id": "125",
        "worksite_id": "worksite_1"
    },
    {
        "_id": "789",
        "type": "signature",
        "user": "alice",
        "pubkey": "65ab64c64ed64ef41a1bvc7d1b",
        "code": "s001"
    },
    {
        "_id": "790",
        "type": "signature",
        "user": "carol",
        "pubkey": "tlmg90834kmn90845kjndf98734",
        "code": "s002"
    },
    {
        "_id": "791",
        "type": "signature",
        "user": "bob",
        "pubkey": "asdf654asdf6854awer654awer654eqr654wra6354f",
        "code": "s003"
    },
    {
        "_id": "_design/projDocs",
        "views": {
          "docsPerWorkSite": {
            "map": "function (doc) {\n  if (doc.type && ['worksitelog', 'document', 'project', 'signature'].indexOf(doc.type) > -1) {\n    if (doc.type == 'worksitelog') {\n      emit([doc.worksite_id, 0], null);\n      for (var i in doc.documents) {\n        emit([doc.worksite_id, Number(i)+1, 'p'], {_id: doc.documents[i].project_id});\n        emit([doc.worksite_id, Number(i)+1, 'd'], {_id: doc.documents[i].document_id});\n        emit([doc.worksite_id, Number(i)+1, 's'], {_id: doc.documents[i].signature_id});\n      }\n    }\n  }\n}"
          }
        },
        "language": "javascript"
    }
  ]
}

将数据保存到磁盘上,命名为stackoverflow_53752001.json

使用Fauxton创建一个名为stackoverflow_53752001的数据库。

这里是一个bash脚本,用于将数据从文件stackoverflow_53752001.json加载到数据库stackoverflow_53752001中。你需要修改前三个参数,然后将其粘贴到(Unix)终端窗口中:

USRID="you";
USRPWD="yourpwd";
HOST="yourdb.yourpublic.work";

COUCH_DATABASE="stackoverflow_53752001";
FILE="stackoverflow_53752001.json";
#
COUCH_URL="https://${USRID}:${USRPWD}@${HOST}";
FULL_URL="${COUCH_URL}/${COUCH_DATABASE}";
curl -H 'Content-type: application/json' -X POST "${FULL_URL}/_bulk_docs"  -d @${FILE};

在Fauxton中,选择数据库stackoverflow_53752001,然后在左侧菜单中选择“设计文档”>>“projDocs”>>“视图”>>“docsPerWorkSite”。
您将看到如下数据:
{"total_rows":17,"offset":0,"rows":[
  {"id":"1235","key":["worksite_1",0],"value":null},
  {"id":"1235","key":["worksite_1",1,"d"],"value":{"_id":"459"}},
          :                     :
          :                     :
  {"id":"1234","key":["worksite_2",4,"p"],"value":{"_id":"123"}},
  {"id":"1234","key":["worksite_2",4,"s"],"value":{"_id":"790"}}
]}

如果您点击右上角的“选项”按钮,您将获得一个选项表单来修改原始查询。请选择:

  • “包括文档”
  • “键之间”
    • “开始键”:[“工作站_1”,0]
    • “结束键”:[“工作站_1”,9999]

点击“运行查询”,您应该能够看到:

{"total_rows":17,"offset":0,"rows":[
  {"id":"1235","key":["worksite_1",0],"value":null,"doc":{"_id":"1235","_rev":"1-de2b919591c70f643ce1005c18da1c54","type":"worksitelog","documents":[{"timestamp":"20180913101502","project_id":"125","document_id":"459","signature_id":"790"}],"worksite_id":"worksite_1"}},
  {"id":"1235","key":["worksite_1",1,"d"],"value":{"_id":"459"},"doc":{"_id":"459","_rev":"1-5422628e475bab0c14e5722a1340f561","type":"document","code":"d001","project_id":"125","worksite_id":"worksite_1"}},
  {"id":"1235","key":["worksite_1",1,"p"],"value":{"_id":"125"},"doc":{"_id":"125","_rev":"1-312dd8a9dd432168d8608b7cd9eb92cd","type":"project","code":"p003"}},
  {"id":"1235","key":["worksite_1",1,"s"],"value":{"_id":"790"},"doc":{"_id":"790","_rev":"1-be018df4ecdf2e6add68a2758b9bd12a","type":"signature","user":"carol","pubkey":"tlmg90834kmn90845kjndf98734","code":"s002"}}
]}

如果您将起始和结束键更改为["worksite_2", 0]["worksite_2", 9999],则可以查看第二个工地的数据。

为了使其正常工作,每次您将新文档和签名写入数据库时,都需要:

  1. 准备一个对象{ "timestamp": "20180921091502", "project_id": "123", "document_id": "457", "signature_id": "791" }
  2. 获取相应的工地日志记录
  3. 将对象附加到documents数组中
  4. 放回已更改的工地日志记录

我假设每个文档有多个签名,因此您需要为每个签名编写一条日志记录。 如果这变得太大,您可以将worksite_id更改为类似worksite_1_201812的内容,这将为每个工地每月提供一个日志,而不会破坏查询逻辑,我想。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接