MongoDB按数组内部元素分组
Posted
技术标签:
【中文标题】MongoDB按数组内部元素分组【英文标题】:MongoDB group by array inner-elements 【发布时间】:2014-02-25 20:35:37 【问题描述】:我有一个文章列表,每个文章都有一个数组属性,其中列出了其中提到的各种个人:
_id:
$oid: "52b632a9e4f2ba13c82ccd23"
,
providerName: "The Guardian",
url: "http://feeds.theguardian.com/c/34708/f/663860/s/3516cebc/sc/38/l/0L0Stheguardian0N0Cmusic0C20A130Cdec0C220Cwaterboys0Efishermans0Eblues0Etour0Ehammersmith/story01.htm",
subject: "The Waterboys – review",
class_artist: [
"paul mccartney"
]
我一直在尝试(未成功)根据过去 7 天内标记的文章数量获取所有艺术家 (class_artist
) 的列表。
我已经做到了:
var date = new Date();
date.setDate(date.getDate() - 7);
db.articles.group(
key: class_artist: 1 ,
cond: class_date: $gt: date ,
reduce: function ( curr, result ) result.cnt++; ,
initial: cnt : 0
).sort(cnt: -1);
但不幸的是,它不是根据单个数组值计算它们,而是根据数组组合(即艺术家列表)。
我尝试使用$unwind
函数,但未能成功。
【问题讨论】:
【参考方案1】:您使用的是什么框架?这不是 MongoDB shell,看起来像 MapReduce 周围的一些奇怪的包装器。在这种情况下,$unwind 将不可用,您需要它供aggregation framework 中的用户使用。这是你想要的 mongo shell:
db.articles.aggregate([
$match: class_date: $gte: date ,
$project: _id: 0, class_artist: 1 ,
$unwind: "$class_artist" ,
$group: _id: "$class_artist", tags: $sum: 1 ,
$project: _id: 0,class_artist: "$_id", tags: 1 ,
$sort: tags: -1
])
如此高效:
-
Filter 按日期,因为您已经为过去 7 天设置了一个变量
Project 只需要我们需要的字段 我们只需要一个!
Unwind 数组,所以我们现在对每个文档中的每个数组元素都有一个记录
Group 来自扩展文档中的艺术家
投影成一种文档格式,您可以使用 _id 作为组乱用
Sort 将结果倒序查看顶部标记的第一个
聚合的好处在于您可以逐步建立这些阶段以查看发生了什么。
根据需要摇动并烘焙到您自己的驱动程序实施或 ODM 框架中。
【讨论】:
仅供参考,“奇怪的包装”格式是group()
command,它在 javascript 中实现,早于聚合框架。另见:MongoDB aggregation comparison: group(), $group and MapReduce.以上是关于MongoDB按数组内部元素分组的主要内容,如果未能解决你的问题,请参考以下文章