有3种CouchDB文档类型:
用户
{ "_id: "user/author1", "type: "user", "name" : "Joe Doe"}
评分
{ "_id: "review/review1", "type" : "review", "content" : "..." }
产品
{ "_id": "product/awesomeproduct", "type" : "product", "reviews": [
{
"author": "author1",
"review_id": "review/review1"
},
{
"author": "author2",
"review_id": "review/review2"
}
]
}
如何从单一视图的文档中获取所有数据?
我尝试使用链接文档,但它可以使用(使用include_docs = true)每个只发出一个:
(coffescript)
(doc) ->
if doc.type is "product"
for review in doc.reviews
emit [doc._id, review.author],{_id: "user/" + review.author}
emit [doc._id, review.author],{_id: review.review_id}
但我想要这样的东西(在单发中获取用户和评论文档):
(doc) ->
if doc.type is "product"
for review in doc.reviews
key = [doc._id, review.author]
value = {"user:" {_id: "user/" + review.author},"review" :{_id: review.review_id}}
emit key, value
有没有可行的方法来实现它?如何在单一视图中加入这些类型的文档?
我希望得到类似这样的结果:
[
key : ["product/awesomeproduct", "author1"],
value : {user: {_id: "user/author1"},review :{_id: "review/review1"}}
doc:
{user: {"_id: "user/author1", "type: "user", "name" : "Joe Doe"},
review: {"_id: "review/review1", "type" : "review", "content" : "..."}
}
]
答案 0 :(得分:4)
看起来像减少功能的经典案例(对不起,对我来说没有咖啡:) :):
<强>地图
function(doc) {
if(doc.type == "product") {
for(review_i in doc.reviews) {
var review = doc.reviews[review_i];
emit([doc._id, review.author],{user: "user/" + review.author, review: review.review_id});
}
}
}
<强>减少强>
function(keys, values) {
return(values);
}
结果(?reduce = true [&amp; group = exact]):
key value
["product/awesomeproduct", "author2"] [{user: "user/author2", review: "review/review1"}]
["product/awesomeproduct", "author1"] [{user: "user/author1", review: "review/review1"}]
您希望发出的数据到底是什么样的?
对上述评论的回复 应该是可能的,除了您想要在视图的返回文档中显示数据的方式。 include_docs表示返回整个doc,就像它一样。看起来您希望在视图和返回的文档中表示相同的数据,因此可能会将文档的结构更改为:
_id : ...
data :
{
user: {"_id: "user/author1", "type: "user", "name" : "Joe Doe"},
review: {"_id: "review/review1", "type" : "review", "content" : "..."}
}
否则,如果您只想要视图键,则值为上述结构,并且不关心返回的doc的结构:
<强>地图
function(doc) {
if(doc.type == "product") {
for(review_i in doc.reviews) {
var review = doc.reviews[review_i];
emit([doc._id, review.author],{
user: {_id: "user/" + review.author},
review: {_id: review.review_id}
});
}
}
}
哪个应该导致:
curl -X GET http://localhost:5984/testdb2/_design/test/_view/test?include_docs=true\&reduce=false
{
"offset": 0,
"rows": [
{
"doc": {
"_id": "product/awesomeproduct",
"_rev": "2-20f0c6cc663e03ab93f8646f09d87db2",
"reviews": [
{
"author": "author1",
"review_id": "review/review1"
},
{
"author": "author2",
"review_id": "review/review1"
}
],
"type": "product"
},
"id": "product/awesomeproduct",
"key": [
"product/awesomeproduct",
"author1"
],
"value": {
"review": {
"_id": "review/review1"
},
"user": {
"_id": "user/author1"
}
}
},
{
"doc": {
"_id": "product/awesomeproduct",
"_rev": "2-20f0c6cc663e03ab93f8646f09d87db2",
"reviews": [
{
"author": "author1",
"review_id": "review/review1"
},
{
"author": "author2",
"review_id": "review/review1"
}
],
"type": "product"
},
"id": "product/awesomeproduct",
"key": [
"product/awesomeproduct",
"author2"
],
"value": {
"review": {
"_id": "review/review1"
},
"user": {
"_id": "user/author2"
}
}
}
],
"total_rows": 2
}
这并不像你在寻找它,但它是我最好的猜测。
答案 1 :(得分:1)
短吻......你做不到。 Couchdb只允许您一次发出一个文档。
获取所需数据有两种方法。
Data modeling considerations适用于Mongodb,但有关如何在NoSQL环境中构建数据的概念与CouchDB相同
答案 2 :(得分:0)
您可以在下面做类似的事情,
function (doc) {
if(doc.type is "product" && doc.reviews.length > 0){
for(x=0; x<doc.reviews.length; x++){
key = [doc._id, review.author]
value = {"user:" {_id: "user/" + review.author},"review" :{_id: review.review_id}}
emit ([key, value])
}
}
}
,这将在您的相关视图中发出两个文档。