如何在Couchdb map/reduce中按用户查看喜爱的用户文档?

如何在Couchdb map/reduce中按用户查看喜爱的用户文档?,couchdb,mapreduce,Couchdb,Mapreduce,My Couchdb数据库作为主文档类型,类似于: { "_id" : "doc1", "type" : "main_doc", "title" : "the first doc" ... } { "_id" : "fav1", "type" : "favorite", "user_id" : "user1", "doc_id" : "doc1" } { "key" : "user1", "value" : ["doc1", "the firs

My Couchdb数据库作为主文档类型,类似于:

{
   "_id" : "doc1",
   "type" : "main_doc",
   "title" : "the first doc"
   ...
}
{
   "_id" : "fav1",
   "type" : "favorite",
   "user_id" : "user1",
   "doc_id" : "doc1"
}
{ "key" : "user1", "value" : ["doc1", "the first doc"] }
还有另一种类型的文档存储用户信息。我希望用户能够将文档标记为收藏夹。不同的用户可以将相同或不同的文档保存为收藏夹。我的想法是引入一个最喜欢的文档来跟踪它,比如:

{
   "_id" : "doc1",
   "type" : "main_doc",
   "title" : "the first doc"
   ...
}
{
   "_id" : "fav1",
   "type" : "favorite",
   "user_id" : "user1",
   "doc_id" : "doc1"
}
{ "key" : "user1", "value" : ["doc1", "the first doc"] }
创建一个以user_id为键的视图很容易,可以获得他们最喜欢的文档id列表。例如:

function(doc) {
   if (doc.type == "favorite") {
      emit(doc.user_id, doc.doc_id);
   }
 }
但是,我想列出收藏夹以显示文档中的用户id、文档id和标题。因此,输出如下内容:

{
   "_id" : "doc1",
   "type" : "main_doc",
   "title" : "the first doc"
   ...
}
{
   "_id" : "fav1",
   "type" : "favorite",
   "user_id" : "user1",
   "doc_id" : "doc1"
}
{ "key" : "user1", "value" : ["doc1", "the first doc"] }
在CouchDB 0.11(刚刚发布)中,包含功能。例如:

function(doc) {
    if(doc.type == "favorite") {
        emit(doc.user_id, {_id: doc.doc_id});
    }
}
当您使用
include_docs=true
查询视图时,您会看到如下JSON:

// ... normal stuff
rows: [
  {
    "key":"user1",
    "value":{"_id":"doc1"},
    "doc": {
      "_id" : "doc1",
      "type" : "main_doc",
      "title" : "the first doc"
      // ...
     }
  },
  {
    // another doc, etc...
  }
]

如果无法在v0.11中使用
include_docs=true
功能,则在为视图/地图发送数据时,必须手头有所有信息

代替传统的“连接”样式,考虑在“代码> MixyODC/<代码>文档中存储一个“最喜欢”用户列表。

{
   "_id" : "doc1",
   "type" : "main_doc",
   "title" : "the first doc",
   "favorited_by": ["user1", "user2"]
   // ...
}
这样,当视图运行时,您可以基于该文档中的信息发出所有内容

function(doc) {
    if(doc.type == "main_doc") {
        for (var a in doc.favorited_by) {
            emit(doc.favorited_by[a], [doc._id, doc.title]);
        }
    }
}

这是一个很酷的新特性,但我不想返回整个文档。我只想要一个只有标题的最喜欢的项目列表。如果用户选择查看文档,我只需要整个文档。是的,我理解。当然,我的解决方案也会迫使您升级。但是我不确定如何在没有“模式”重构的情况下实现你想要的。我会考虑重构文档如何被配置来适应这个。有什么建议吗?我会添加另一个答案。如果你可以做一个include_docs,然后指定一个子集的文档字段,你想包括在视图中,那就太酷了。或者在单独的请求中获取文档标题真的不会有太多开销吗?我已经有了另一个输出文档ID和标题的视图。我试图避免再次调用数据库来获取每个收藏夹的文档标题。我可能在这里遇到了可伸缩性问题吗?如果很多用户试图将此文档添加为收藏夹,我可能会遇到很多冲突。是的,你是对的。这是一种取舍,取决于您的预期使用情况。另一个想法是以另一种方式存储它:在用户对象中存储
[“doc\u id”,“doc Title”]
元组。这将需要三次往返(1:获取主文档;2:获取用户文档,3:使用新元组更新用户文档),但是您可能已经在必要的时候准备好了所有这些文档。与通过联接样式文档在读取时进行多个查找相比,我仍然更喜欢这种方式。我希望对最喜欢的查找进行一次读取操作。我还试图避免将文档标题复制到其他文档中,因为如果在实际文档中更新了标题,则复制的标题已过期,或者我需要查找并更新所有将此文档作为收藏夹的用户文档。我现在只需读取视图一次,即可查找用户的收藏夹文档ID。然后,对于每个最喜欢的,我都会用另一本书来查找标题。