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

Problems joining two documents via Map-Function (CouchDB)

我的目标是 link 将两个文档放在一起并取回它们的详细信息。

你的 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 table 作为结果。

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

列表函数的结果:

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's Linked Documents in a View
Best way to do one-to-many "JOIN" in CouchDB

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

所以,如果你想显示 _id,你可以这样做:'<td>' + row.value._id + '</td>'。但是您要求显示 namemodel。查看 json 文件,该信息位于 doc 键下。所以你要找的似乎是:

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

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

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