对于CouchDB,我是新手.我来自.NET SQL Server世界.
在通过CouchDB浏览权威指南时,我觉得"这太棒了".现在我正在测试我学到的一些东西,希望在现实世界中实现它.
几周前我刚刚注册了Cloudant帐户,并开始使用它进行一些测试/学习.
在弄乱链接文档时,背后的整个理论看起来很简单,也是互联网上的海峡前沿例子.我想从具有不同链接文档数组的文档中检索某些信息,这些文档本身具有链接文档数组.就像连接到多对多关系表的多SQL Server一样.你会看到下面的代码.希望这是有道理的.
以此SQL查询为例.假设每个表中只有一个条目,我们应该返回一条记录,其中包含具有给定sku的鞋子的所有细节.但如果我们有多种鞋码,我们就不得不再写一些代码了.
select ci.sku
,sc.color
,ss.size
,si.url
from CatalogItem ci
join ShoeImages si
on ci.sku = si.sku
and ci.sku = '656F-PINSEC12'
join ShoeSizes ss
on ci.sku = ss.sku
join ShoeColors sc
on ci.sku = sc.sku
Run Code Online (Sandbox Code Playgroud)
我希望CouchDB通过SKU返回以下JSON,网址为https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22
{
"_id": "689fe6982f4d604541db67ee4050a535",
"_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
"type": "catalogue-item",
"sku": "656F-PINSEC12",
"upc": "8549875231",
"shoe-colors":
[
{
"color": "black/houndstooth"
"shoe-sizes":
[
{
"size": 5,
"IsSizeAvailable": true
},
{
"size": 6,
"IsSizeAvailable": true
},
{
"size": 7,
"IsSizeAvailable": true
},
{
"size": 8,
"IsSizeAvailable": true
},
{
"size": 9,
"IsSizeAvailable": true
},
{
"size": 10,
"IsSizeAvailable": true
},
{
"size": 11,
"IsSizeAvailable": true
},
{
"size": 12,
"IsSizeAvailable": true
},
{
"size": 13,
"IsSizeAvailable": true
},
{
"size": 14,
"IsSizeAvailable": true
}
],
"shoe-images":
[
{
"full-images":
[
"http://www.someurl.com/full/656F-PINSEC12.jpg"
],
"thumbnail-images":
[
"http://www.someurl.com/thumb/656F-PINSEC12.jpg"
]
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
给出以下文档和map/reduce:
//--catalog item
{
"_id": "689fe6982f4d604541db67ee4050a535",
"_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
"type": "catalogue-item",
"sku": "656F-PINSEC12",
"upc": "8549875231",
"shoe-colors": [
{
"_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
"shoe-images": [
{
"_id": "7b547bae4ac911c6f05b97eba6cb355a"
}
],
"shoe-sizes": [
{
"_id": "12b6289d558d7ceb5bef725091666ce5"
}
]
}
]
}
//--shoe images
{
"_id": "7b547bae4ac911c6f05b97eba6cb355a",
"_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
"type": "shoe-images",
"sku": "656F-PINSEC12",
"color": "Black/Houndstoot",
"full-images": [
"http://www.someurl.com/full/656F-PINSEC12.jpg"
],
"thumbnail-images": [
"http://www.someurl.com/thumb/656F-PINSEC12.jpg"
]
}
//--shoe color
{
"_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
"_rev": "2-e5d07c00a0261c231dd2be9b26a6c0dc",
"type": "shoe-color",
"sku": "656F-PINSEC12",
"color": "black/houndstooth"
}
//--shoe sizes
{
"_id": "12b6289d558d7ceb5bef725091666ce5",
"_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
"type": "shoe-sizes",
"sku": "656F-PINSEC12",
"shoe-color": "black/houndstooth",
"shoe-sizes": [
{
"size": 5,
"IsSizeAvailable": true
},
{
"size": 6,
"IsSizeAvailable": true
},
{
"size": 7,
"IsSizeAvailable": true
},
{
"size": 8,
"IsSizeAvailable": true
},
{
"size": 9,
"IsSizeAvailable": true
},
{
"size": 10,
"IsSizeAvailable": true
},
{
"size": 11,
"IsSizeAvailable": true
},
{
"size": 12,
"IsSizeAvailable": true
},
{
"size": 13,
"IsSizeAvailable": true
},
{
"size": 14,
"IsSizeAvailable": true
}
]
}
//--map/reduce
{
"_id": "_design/catalog",
"_rev": "4-de5baf04b485768de12d78e5a0e5aa5e",
"views": {
"item": {
"map": "function(doc)
{
if (doc.type === 'catalog-item')
{
emit([doc.sku, doc], null);
if (doc.shoe-colors)
{
for (var sc in doc.shoe-colors)
{
emit([doc.sku, Number(sc)+1], {_id: doc.shoe-colors[sc]._id});
for (var si in doc.shoe-colors[sc].shoe-images)
{
emit([doc.sku, Number(si)+1], {_id: doc.shoe-colors[sc].shoe-images[si]._id});
}
for (var sz in doc.shoe-colors[sc].shoe-sizes)
{
emit([doc.sku, Number(sz)+1], {_id: doc.shoe-colors[sc].shoe-sizes[sz]._id});
}
}
}
}
}"
}
}
}
Run Code Online (Sandbox Code Playgroud)
可能有更好的方法来实现这一点,但我想看看是否有可能拥有一个包含链接文档数组的文档,这些文档也包含一系列链接文档.但是我的map/reduce没有返回任何东西.它返回的全部是:
{"total_rows":0,"offset":0,"rows":[
]}
Run Code Online (Sandbox Code Playgroud)
我猜测有人不会将所有信息存储在单个文档中,因为我们添加新的显示大小或将鞋号标记为不可用,这意味着必须将所有先前的值传递给CouchDB更新一个字段.
希望我的问题有道理Oo__oO
这方面的诀窍是远离JOIN的思考.链接文档为您提供了一种技术,可以根据另一种文档的属性对一种类型的文档进 这可以使用两个功能的组合:
举个例子,假设你有文件
{
"_id": "111",
"type", "shoe",
"sku": "656F-PINSEC12",
"shoe-color": "black/houndstooth",
"imageId": "222"
}
Run Code Online (Sandbox Code Playgroud)
和
{
"_id": "222",
"type": "image",
"full-images": ["http://www.someurl.com/full/656F-PINSEC12.jpg"]
"thumbnail-images": ["http://www.someurl.com/thumb/656F-PINSEC12.jpg"]
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用map函数索引SKU的图像:
function(doc) {
if(doc.type === "shoe") {
emit(doc.sku, {_id: doc.imageId });
}
}
Run Code Online (Sandbox Code Playgroud)
同样重要的是要意识到map函数仅对保存的原始文档进行操作.
我认为在您的示例中,"目录项"和"鞋色"文档是多余的.你可以定义一个地图功能来索引SKU的"鞋子图像"和"鞋子尺寸"文件,例如
function(doc) {
if(doc.SKU) {
emit(doc.SKU, null);
}
}
Run Code Online (Sandbox Code Playgroud)
假设这被分配给视图"item-details",您的查询:
应该回来
{
"total_rows":2,
"offset":0,
"rows":
[
{
"id":"7b547bae4ac911c6f05b97eba6cb355a",
"key":"656F-PINSEC12",
"value":null,
"doc":{
"_id": "7b547bae4ac911c6f05b97eba6cb355a",
"_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
"type": "shoe-images",
"sku": "656F-PINSEC12",
"color": "Black/Houndstoot",
"full-images": [
"http://www.someurl.com/full/656F-PINSEC12.jpg"
],
"thumbnail-images": [
"http://www.someurl.com/thumb/656F-PINSEC12.jpg"
]
}
},
{
"id":"12b6289d558d7ceb5bef725091666ce5",
"key":"656F-PINSEC12",
"value":null
"doc":{
"_id": "12b6289d558d7ceb5bef725091666ce5",
"_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
"type": "shoe-sizes",
"sku": "656F-PINSEC12",
"shoe-color": "black/houndstooth",
"shoe-sizes": [
{
"size": 5,
"IsSizeAvailable": true
},
{
"size": 6,
"IsSizeAvailable": true
},
{
"size": 7,
"IsSizeAvailable": true
},
{
"size": 8,
"IsSizeAvailable": true
},
{
"size": 9,
"IsSizeAvailable": true
},
{
"size": 10,
"IsSizeAvailable": true
},
{
"size": 11,
"IsSizeAvailable": true
},
{
"size": 12,
"IsSizeAvailable": true
},
{
"size": 13,
"IsSizeAvailable": true
},
{
"size": 14,
"IsSizeAvailable": true
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
如果要将这些结果合并到单个JSON文档中,可以查看使用list函数生成自定义JSON输出.但是,我不确定这会让你受益匪浅.
看起来您通常会使用更精细的数据模型(例如,每个鞋子/尺寸组合可能是单独的文档),并使用地图函数来聚合给定SKU的数据.