通过Map-Function(CouchDB)连接两个文档的问题

时间:2017-08-11 20:43:10

标签: javascript mapreduce couchdb

我的目标是将两个文档链接在一起并获取其详细信息。

您的CouchDB文档是什么?

汽车

{
    "_id": "car.123",
    "type": "car",
    "name": "Tesla",
    "model": "Semi Truck"
},
{
    "_id": "car.456",
    "type": "car",
    "name": "Tesla",
    "model": "Roadster"
}

制造商

{
"_id": "manu.123",
"type": "manufacturer",
"name": "Tesla Inc.",
"cars": ["car.123", "car.456"]
}

结果如何?

这里我想使用List-Function并生成一个HTML表格。

Name (Manufacturer) | Name (Car) | Model (Car)
------------------- | ---------- | ----------------
Tesla Inc.          | Tesla      | Semi Truck
Tesla Inc.          | Tesla      | Roadster 

你在哪里停留?

我很难将头部缠绕在地图功能上。这是我到目前为止:

function(doc) {
    if (doc) {
        // Give me the ID and the name of the manufacturer 
        emit(doc._id, doc.name); 
        // Check if the document has at least one car in its array
        if (doc.cars < 0) {
            // Give me for every car their details (eg. name & model)
            for (var i in doc.cars) {
                emit(doc.name, {_id: doc.cars[i]});
            }
        }
    }
}

我使用的查询:
http://localhost:5984/my-db/_design/my-design/_view/my-view?key="Tesla Inc."&include_docs=true

list函数的结果:

ID       | Key        | Value
-------- | ---------- | ---------------
manu.123 | Tesla Inc. | [object Object]
manu.123 | Tesla Inc. | [object Object]

我使用此列表功能:

function(head, req){
    start({
        'headers': {
            'Content-Type': 'text/html'
        }
    });
    send('<html><body><table>');
    send('<tr><th>ID</th><th>Key</th><th>Value</th></tr>')
    while(row = getRow()){
        send(''.concat(
            '<tr>',
            '<td>' + row.id + '</td>',
            '<td>' + row.key + '</td>',
            '<td>' + row.value + '</td>',
            '</tr>'
        ));
    }
    send('</table></body></html>');
}

json输出:

{
  "total_rows": 10,
  "offset": 8,
  "rows": [
    {
      "id": "manu.123",
      "key": "Tesla Inc.",
      "value": {
        "_id": "car.123"
      },
      "doc": {
        "_id": "car.123",
        "_rev": "1-7291266e7f81917fef1d0cfa104a39ca",
        "type": "car",
        "name": "Tesla",
        "model": "Semi Truck"
      }
    },
    {
      "id": "manu.123",
      "key": "Tesla Inc.",
      "value": {
        "_id": "car.456"
      },
      "doc": {
        "_id": "car.456",
        "_rev": "1-c5c67f5d5abeda1b77c02f003ec72a9f",
        "type": "car",
        "name": "Tesla",
        "model": "Roadster"
      }
    }
  ]
}

您的确切问题是什么?

如何将[object Object]替换为我的汽车的实际值(例如名称和型号)?

我已经进行了以下资源,但他们没有帮助我:
CouchDB's Linked Documents in a View
couchdb views tied between two databases?
combine multiple documents in a couchdb view
Couchdb join two documents using key
CouchDB's Linked Documents in a View
Best way to do one-to-many "JOIN" in CouchDB

2 个答案:

答案 0 :(得分:1)

在您的示例中,row.value等于一个对象,其中一个案例是{ "_id": "car.123" }。在JavaScript中,当您尝试将字符串与对象连接时,您将获得[object Object],这将在您的列表函数中发生:'<td>' + row.value + '</td>'

因此,如果您想显示_id,可以执行:'<td>' + row.value._id + '</td>'。但是您要求显示名称模型。查看json文件,该信息位于doc密钥下。所以看起来你正在寻找的是:

'<td>' + row.doc.name + ' ' + row.doc.model + '</td>'

答案 1 :(得分:1)

除了Ignacio之前的回答,您还可以改进文档设计中的两件事。

  • 将制造商的_id添加到汽车,而不是制造商的汽车_id数组。这样,您就不必处理不一致的数据:当您删除汽车文档时,您也不必编辑制造商。这在多用户场景中尤为重要。如果一个用户添加汽车,而另一个用户移除同一制造商的汽车怎么办?这可能会导致冲突和数据不一致。
  • 您还可以通过将制造商的名称另外添加到汽车文档中来对数据进行非规范化。这样,您就不必加入文档。 CouchDB在数据主要被读取时表现优异(例如在典型的Web或移动应用程序中),因此您通常也应优化读取。此外,map / reduce查询将更容易编写。