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按数组内部元素分组的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB按数组中的元素分组

MongoDB计数按数组元素分组的数组中的匹配字符串

Mongodb:按元素分组并根据条件显示子文档计数并按日期对文档进行排序

如何使用 MongoDB 根据数组元素对记录进行分组

MongoDB 对数组中的元素进行分组

MongoDB 实用数组聚合操作 (2)