Couchdb 如何在一个视图中链接多个文档

Couchdb 如何在一个视图中链接多个文档,couchdb,Couchdb,有3种CouchDB文档类型: 使用者 复习 { "_id: "review/review1", "type" : "review", "content" : "..." } 产品 { "_id": "product/awesomeproduct", "type" : "product", "reviews": [ { "author": "author1", "review_id": "review/review1" }, { "a

有3种CouchDB文档类型:

使用者

复习

{ "_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):

(辅助脚本)

但是我想要这样的东西(在单个文件中获取用户和审阅文档):

有什么可能的方法来实现它吗?如何在单个视图中连接这些类型的文档

我想得到这样的结果:

[
  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" : "..."}
     }

]

似乎是reduce函数的经典案例(对不起,我没有咖啡:):

地图

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(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}
                            });
        }
    }
}
减少

function(keys, values) {
    return(values);
}
结果(?reduce=true[&group=exact]):

您希望发出的数据看起来像什么

对上述评论的回应 应该是可能的,但您希望在视图返回的文档中显示数据的方式除外。include_docs意味着按原样返回整个文档。似乎您希望在视图和返回的文档中表示相同的数据,因此可以将文档的结构更改为:

_id : ...
data : 
    {
        user: {"_id: "user/author1", "type: "user", "name" : "Joe Doe"},
        review: {"_id: "review/review1", "type" : "review", "content" : "..."}
    }
否则,如果您只希望查看键、值为上述结构,而不关心返回的文档的结构:

地图

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(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
}

这并不是你想要的,但这是我最好的猜测。

似乎是reduce函数的经典案例(对不起,我没有咖啡:):

地图

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(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}
                            });
        }
    }
}
减少

function(keys, values) {
    return(values);
}
结果(?reduce=true[&group=exact]):

您希望发出的数据看起来像什么

对上述评论的回应 应该是可能的,但您希望在视图返回的文档中显示数据的方式除外。include_docs意味着按原样返回整个文档。似乎您希望在视图和返回的文档中表示相同的数据,因此可以将文档的结构更改为:

_id : ...
data : 
    {
        user: {"_id: "user/author1", "type: "user", "name" : "Joe Doe"},
        review: {"_id: "review/review1", "type" : "review", "content" : "..."}
    }
否则,如果您只希望查看键、值为上述结构,而不关心返回的文档的结构:

地图

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(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
}

这并不是你真正想要的,但这是我最好的猜测。

简而言之,你不能。Couchdb一次只允许发出一个文档

有两种方法可以获取所需的数据

  • 保持结构不变,并在客户端代码中手动执行连接
  • 对数据进行非规范化处理。这里的非规范化类似于将评审放在产品文档中

  • 适用于Mongodb,但有关如何在NoSQL环境中构造数据的概念与CouchDB相同,简称anwser…您不能。Couchdb一次只允许发出一个文档

    有两种方法可以获取所需的数据

  • 保持结构不变,并在客户端代码中手动执行连接
  • 对数据进行非规范化处理。这里的非规范化类似于将评审放在产品文档中

  • 适用于Mongodb,但有关如何在NoSQL环境中构造数据的概念与CouchDB相同,您可以执行以下操作:

    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])
        }
      }
    }
    
    功能(doc){
    如果(文档类型为“产品”&&doc.reviews.length>0){
    
    对于(x=0;x您可以执行以下操作

    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])
        }
      }
    }
    
    功能(doc){
    如果(文档类型为“产品”&&doc.reviews.length>0){
    
    对于(x=0;xReduce函数可以工作,但不幸的是,它不能与include_docs=true一起使用。因此,我没有从其他文档中获取该数据。我用我需要的结果更新了帖子。Reduce函数可以工作,但不幸的是它不能与include_docs=true一起使用。因此,我没有从其他文档中获取该数据。我用结果更新了帖子我需要。啊哈,好。我在下面附上了另一个答案。啊哈,好。我在下面附上了另一个答案。