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

时间:2013-04-17 22:14:10

标签: couchdb

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

]

3 个答案:

答案 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只允许您一次发出一个文档。

获取所需数据有两种方法。

  1. 保持结构不变,并在客户端代码中自行手动执行连接。
  2. 反规范化您的数据。这里的非规范化就像将评论放在产品文档中一样。
  3. 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])
    }
  }
}

,这将在您的相关视图中发出两个文档。