View CouchDB返回一个到多个中的第一个

View CouchDB返回一个到多个中的第一个,view,couchdb,View,Couchdb,我有一个包含任务的沙发数据库。这些任务可以有多个注释。我想要一个视图,返回所有任务,每个任务只有一个最新的注释 想象一下,这就像得到所有的博客帖子,以及每个帖子的最新评论一样 Ie这样的事情是可能的吗?哦,你有很多选择!什么最有效在很大程度上取决于您的用例 与客户端过滤分离 在这种方法中,客户机获取所有信息并决定显示什么。您可以从显示最新的评论开始,如果用户想要查看更多,它将是即时的,因为您已经收到了数据,所以不再有请求 示例注释: { “_id”:“89f34369f0a50685bcb068

我有一个包含任务的沙发数据库。这些任务可以有多个注释。我想要一个视图,返回所有任务,每个任务只有一个最新的注释

想象一下,这就像得到所有的博客帖子,以及每个帖子的最新评论一样


Ie这样的事情是可能的吗?

哦,你有很多选择!什么最有效在很大程度上取决于您的用例

与客户端过滤分离 在这种方法中,客户机获取所有信息并决定显示什么。您可以从显示最新的评论开始,如果用户想要查看更多,它将是即时的,因为您已经收到了数据,所以不再有请求

示例注释:

{
“_id”:“89f34369f0a50685bcb0682103003b2d”,
“修订版”:“1-f64ffb6e374b8055b2fcdaa040f26a4f”,
“任务ID”:“89f34369f0a50685bcb0682103002037”,
“文本”:“使用驾驶员侧车门门柱中的胎压”,
“类型”:“注释”,
“时间戳”:300
}
示例任务:

{
“_id”:“89f34369f0a50685bcb0682103002037”,
“修订版”:“1-62490798662429DC35BA113D4772DE”,
“类型”:“任务”,
“文本”:“检查轮胎压力”
}
查看以向您提供任务和评论:

{
“\u id”:“\u设计/mydesign”,
“修订版”:“1-3ac9fa693c8b20f9598a4c667009ed45”,
“意见”:{
“带有最新注释的任务”:{
“映射”:“函数(doc){if(doc.type=='task'){emit([doc.\u id,0],doc);}否则if(doc.type=='comment'){emit([doc.taskId,1],doc);}”
}
}
}
结果,您的所有任务都将具有
键[1]==0
,而所有注释都具有
键[1]==1

独立的和最近嵌入的 <>如果我有一个重读的应用程序收到了大量的评论,我会把建模注释看作一个单独的文档,并将最新的注释嵌入到任务中。p>
  • 赞成:现在每个任务都有需要显示的所有信息
  • 缺点:客户端现在需要确保每个注释都作为注释持久化,并更新任务
示例注释:

{
“_id”:“89f34369f0a50685bcb0682103003b2d”,
“修订版”:“1-f64ffb6e374b8055b2fcdaa040f26a4f”,
“任务ID”:“89f34369f0a50685bcb0682103002037”,
“文本”:“使用驾驶员侧车门门柱中的胎压”,
“类型”:“注释”,
“时间戳”:300
}
示例任务:

{
“_id”:“89f34369f0a50685bcb0682103002037”,
“修订版”:“1-62490798662429DC35BA113D4772DE”,
“类型”:“任务”,
“文本”:“检查轮胎压力”,
“最新评论”:{
“_id”:“89f34369f0a50685bcb0682103003b2d”,
“修订版”:“1-f64ffb6e374b8055b2fcdaa040f26a4f”,
“任务ID”:“89f34369f0a50685bcb0682103002037”,
“文本”:“使用驾驶员侧车门门柱中的胎压”,
“类型”:“注释”,
“时间戳”:300
}
}
在这种方法中,获取最近的注释是在写入时处理的,因此检索注释的查询非常简单

每一条评论都嵌入其中 如果注释很少出现,那么将它们全部嵌入到这样的任务中可能是有意义的:

{
“_id”:“89f34369f0a50685bcb0682103000640”,
“修订版”:“1-5FB40B1D24BDBACBB652112DFB3E3E5”,
“文本”:“拿起牛奶”,
“评论”:[
{“timestamp”:100000000,“text”:“first”},
{“timestamp”:90000000,“text”:“last”},
{“时间戳”:80000000,“文本”:“中间”}
]
}
只提取最近的注释的合理方法是按时间戳降序排序
doc.comments
,然后获取第一个注释

我们不能这样做,因为;它们必须没有副作用。因此,尽管很容易使用比较器调用
doc.comments.sort
,但这将尝试对注释数组进行修改,并抛出一个错误:

Log::函数引发了异常(新类型错误(“doc.comments.sort(函数(a,b){return b.timestamp-a.timestamp;})为只读”,“未定义”,1))和doc.\u id 89f34369f0a5068bcb062103000640
相反,我们可以要求给我们一个数组的浅拷贝

var recentComments=doc.comments.slice()//我们可以自由修改新数组
.sort(函数(a,b){//就地排序
返回b.timestamp-a.timestamp;//按时间戳降序
}).切片(0,1);//仅将第一个结果作为数组
现在我们有了一个评论数组,其中只包含最新的评论。我们已经知道无法重新分配它,所以让我们构建另一个对象,以提供给我们的
emit
函数。注意:新对象应该包含您关心的所有字段

emit(doc.\u id,{text:doc.text,comments:recentComments});
所有这些使我们对以下方面有了一个最终的看法:

{
“\u id”:“\u设计/mydesign”,
“修订版”:“1-be95f2e2a699bb7182184dbc0729d3ce”,
“意见”:{
“带有最新注释的任务”:{
“映射”:“函数(doc){emit(doc._id,{text:doc.text,comments:doc.comments.slice().sort(函数(a,b){返回b.timestamp-a.timestamp;}).slice(0,1)};}”
}
}
}

注释是嵌入到任务中还是存储为单独的文档?存储为单独的文档。是否可以使用map/reduce来实现这一点?我想您提到的第一个解决方案是最好的,尽管我不会让客户机进行过滤,而是使用NodeJS。问题是,我目前正在返回所有任务和注释,但它变得相当大,需要一段时间才能加载到浏览器中。因此,使用node来精简到只包含最新的评论就可以了。我只是希望CouchDB中会有一些魔法可以让它发生。