我刚刚开始使用Cloudant而我无法理解地图功能。我一直在摆弄下面的数据,但它并没有按照我的预期进行。
关系是,用户可以有很多车辆。车辆属于1个用户。车辆'userId'是用户的关键。有一些冗余,因为用户_id和userId是相同的,后来不需要猜测。
无论如何,我怎样才能找到一个/每个用户,属于它的车辆?我最接近试验和错误的结果是显示每辆车的车主,但我想反过来,用户和属于它的车辆。我发现的所有示例都使用另一个“加入”两个或更多文档的文档,但我不需要这样做?
正确方向的任何一点都值得赞赏 - 我真的不知道。
function (doc) {
if (doc.$doctype == "vehicle")
{
emit(doc.userId, {_id: doc.userId});
}
}
编辑:越来越近了。我不确定我到底想要什么,但结果看起来有点乱 - '。行[0]是用户文档,行[n> 0]是车辆文件。我认为使用启动键/结束键时它很好,但没有结果有点混乱。
function (doc) {
if (doc.$doctype == 'user') {
emit([doc._id, 0], doc);
} else if (doc.$doctype == 'vehicle') {
emit([doc.userId, 1, doc._id], doc);
}
}
用户被描述为
{
"_id": "user:10",
"firstname": “firstnamehere",
"secondname": “secondnamehere",
"userId": "user:10",
"$doctype": "user"
}
车辆被描述为,
{
"_id": "vehicle:4002”,
“name”: “avehicle”,
"userId": "user:10",
"$doctype": "vehicle",
}
答案 0 :(得分:1)
你正朝着正确的方向前进!你已经掌握了全局ID。以某种形式将文档的类型作为ID的一部分是一个非常好的主意,以便您以后不会感到困惑(所有文档都在同一个" pot")。
以下是您当前解决方案的一些小问题(在回答您的实际问题之前):
不要在emit(key, value)
中将文档作为值发出。您始终可以通过查询include_docs=true
来请求属于视图行的文档。将doc作为视图值可以大大增加视图索引。如果您不需要特定值,请使用emit(key, null)
。
您也不需要发票值中的ID。您无论如何都会获得属于视图行的文档的ID。
现在解决您的用户聚合车辆的问题。你得到了正确的基本模式。此模式称为查看排序规则,您可以阅读更多相关信息in the CouchDB docs(忽略它位于" Couchapp"部分)。
使用视图排序规则的技巧是您返回两种或更多类型的文档,但要确保它们以允许直接分组的方式排序。因此,了解CouchDB如何对视图结果进行排序非常重要。有关该collation specification的更多信息,请参阅Step-by-step guide to build Qt-SQL-driver-plugin for SQLite-DB with SQLCipher-extension。理解视图排序规则的一个重要关键是具有数组键的行按键元素排序。因此,当两行具有相同的key[0]
时,它们按key[1]
排序。如果相同,则考虑key[2]
,依此类推。
您的地图功能frist按用户ID(key[0]
)对用户和车辆进行分组。然后,您的地图函数会使用0
在密钥的第二个元素中1
之前排序的事实,因此您的视图将包含以下内容:
如您所见,用户的车辆会立即跟随他们的用户。因此,您可以将此结果分组为聚合,而无需执行昂贵的排序或查找操作。
请注意,用户根据其ID进行排序,用户内的车辆也会根据其ID进行排序。这是因为您使用了键数组中的ID。
如果您无法根据自己的需求进行查询,那么该视图并不值得。您拥有的视图支持以下查询:
_all_docs
视图)我们想要查询范围,因此我们在查询中使用startkey
和endkey
:
startkey=["user:1", 0]
endkey=["user:3", 1, {}]
请注意使用{}
作为哨兵值,这是必需的,以便结束键大于任何具有["user:3", 1, (anyConceivableVehicleId)]