【发布时间】:2014-04-08 03:36:36
【问题描述】:
我收藏了大量歌曲,并希望以数组形式收集每周播放次数最多的歌曲。例如:
{
"_id" : {
"title" : "demons savaites hitas",
"name" : "imagine dragons"
},
"value" : {
"weeks" : [
{
"played" : 56,
"week" : 9,
"year" : 2014
}
]
}
}
有时会变成:
{
"_id" : {
"title" : "",
"name" : "top 15"
},
"value" : {
"played" : 1,
"week" : 8,
"year" : 2014
}
}
我从中获取数据的集合被命名为歌曲,并且在添加歌曲时会一直添加新字段。没有唯一的艺术家姓名或歌名,集合中的每个文档都如下所示:
{
"_id" : ObjectId("530536e3d4ca1a783342f1c8"),
"week" : 8,
"artistname" : "City Shakerz",
"songtitle" : "Love Somebody (Summer 2012 Mix Edit)",
"year" : 2014,
"date" : ISODate("2014-02-19T22:57:39.926Z")
}
我现在想做一个 mapreduce,将新的一周添加到数组中。它现在覆盖它。 我还注意到,当尝试使用新的 mapreduce 更改为数组时,并不是所有播放的都被计算在内。
新的 mapreduce 几周后无法正常工作:
map = function () {
if (this.week == 9 && this.year == 2014) emit({title:this.songtitle.toLowerCase(), name:this.artistname.toLowerCase()}, {played:1, week:this.week, year:this.year});
}
reduce = function(k, values) {
var result = {};
result.weeks = new Array();
var object = {played:0, week: 0, year: 0};
values.forEach(function(value) {
object.played += value.played;
object.week = value.week;
object.year = value.year;
});
result.weeks.push(object);
return result;
}
db.songs.mapReduce(map,reduce,{out: {reduce:"played2"}})
这是我使用的旧的,是每周和歌曲集合中的一个新字段:
map = function () {
if (this.week == 10 && this.year == 2014) emit({title:this.songtitle.toLowerCase(), name:this.artistname.toLowerCase(), week:this.week, year:this.year}, {count:1});
}
reduce = function(k, values) {
var result = {count: 0,};
values.forEach(function(value) {
result.count += value.count;
});
return result;
}
db.songs.mapReduce(map,reduce,{out: {merge:"played"}})
我现在从 play2 那里得到来自 toplist 的信息,如下所示:
db.played2.find({'_id.week': 9,'_id.year': 2014}).sort(array("value.count" => -1)).limit(50)
上面的行可以包含任何错字,因为我使用 mongoclient for php 并且需要为您将其更改为 javascript 语法。
我做错了什么?
【问题讨论】:
-
您能否介绍一下您的原始集合的结构。我的观点是我不认为你需要 mapReduce 并且可能有更好的方法。
-
@NeilLunn - 我已经编辑了文档中的问题以及该集合的工作原理。它只是一个很长的 feed-collection,包含最后播放的歌曲,新歌一直在添加,大约每秒 10 首。
-
试试答案中的聚合语句。聚合管道的运行速度比 map reduce 快得多,这似乎符合您想要的结果。
-
我想为一个歌曲标题和艺术家姓名添加几周,主要是因为我想查看一首歌曲在几周内的变化。那么每周两个聚合有点苛刻。
-
只需更改您的标准。如果你只匹配一首歌和艺术家,因为它是关键的一部分,那么结果中只会有那首歌,因为它出现的每一周。因为你不需要它,所以在最后删除限制。匹配部分只是一个标准查询,就像您要查找的那样。你不熟悉吗?还有更多问题,然后评论答案而不是您的问题。
标签: arrays mongodb mapreduce pymongo