假设我在CouchDB数据库中存储了两种类型的文档.首先是财产类型设置为联系,第二个是电话.联系人类型文档有另一个名为name的属性.电话类型具有属性编号和contact_id,以便它可以引用联系人.这是微不足道的一对多的场景,其中一个联系人可以有N个电话号码(我知道他们可以嵌入单一接触文件,但我需要证明一个与不同的文件一对多的关系).
Scott的原始示例数据有2个电话号码,Matt有1个号码:
{_id: "fc93f785e6bd8c44f14468828b001109", _rev: "1-fdc8d121351b0f5c6d7e288399c7a5b6", type: "phone", number: "123456", contact_id: "fc93f785e6bd8c44f14468828b00099f"} {_id: "fc93f785e6bd8c44f14468828b000f6a", _rev: "1-b2dd90295693dc395019deec7cbf89c7", type: "phone", number: "465789", contact_id: "fc93f785e6bd8c44f14468828b00099f"} {_id: "fc93f785e6bd8c44f14468828b00099f", _rev: "1-bd643a6b0e90c997a42d8c04c5c06af6", type: "contact", name: "Scott"} {_id: "16309fcd03475b9a2924c61d690018e3", _rev: "1-723b7c999111b116c353a4fdab11ddc0", type: "contact", name: "Matt"} {_id: "16309fcd03475b9a2924c61d69000aef", _rev: "3-67193f1bfa8ed21c68e3d35847e9060a", type: "phone", number: "789456", contact_id: "16309fcd03475b9a2924c61d690018e3"}
地图功能:
function(doc) { if (doc.type == "contact") { emit([doc._id, 1], doc); } else if (doc.type == "phone") { emit([doc.contact_id, 0], doc); } }
减少功能:
function(keys, values) { var output = {}; for(var elem in values) { if(values[elem].type == "contact") { output = { "ID": values[elem]._id, "Name": values[elem].name, "Type": values[elem].type, "Phones": [] }; } else if (values[elem].type == "phone") { output.Phones.push({ "Number": values[elem].number, "Type": values[elem].type }); } } return output; }
由于Map函数中的键,group_level设置为1.现在我可以通过附带的手机获取我的联系人,例如:
http://localhost:5984/testdb2/_design/testview/_view/tv1?group_level=1
或者像这样搜索与startkey和endkey的某些联系:
http://localhost:5984/testdb2/_design/testview/_view/tv1?group_level=1&startkey=[%22fc93f785e6bd8c44f14468828b00099f%22]&endkey=[%22fc93f785e6bd8c44f14468828b00099f%22,{}]
结果看起来正是我想要的 - 联系人将根据一对多关系嵌入手机.这就是问题:这是如何在CouchDB中使用MapReduce函数的正确方法吗?使用此方法时是否存在任何显着的性能问题?
一般来说,如果不这样做,则使用较少的磁盘空间emit(...,doc)
.
您可能想要重新考虑具有reduce功能.实际上没有必要获得您需要的数据.例如,如果您拥有大量记录,则以下内容可能会占用更少的磁盘空间并执行得更好.
此外,我认为在文件包含的reduce函数中构建更多数据是违反CouchDB的.在这种情况下你不是那样做的,但是你遵循的模式可能会导致你以后遇到麻烦.它被称为减少是有原因的.:-)
所以像这样的东西更像CouchDB方式:
查询特定联系人,如下所示: 当然,你没有得到与以前相同的JSON结构的结果,但我相信这在CouchDB中表现更好.function(doc) {
if (doc.type == "contact") {
emit([doc._id, 0], {
"Name": doc.name,
"Type": doc.type
});
} else if (doc.type == "phone") {
emit([doc.contact_id, 1], {
"Number": doc.number,
"Type": doc.type
});
}
}
emit(...,doc)
http://localhost:5984/testdb2/_design/testview/_view/tv1?
startkey=[%22fc93f785e6bd8c44f14468828b00099f%22, 0]
&endkey=[%22fc93f785e6bd8c44f14468828b00099f%22,1]