计算行数并仅获取 MongoDB 中的最后一行

Count number of rows and get only the last row in MongoDB

我收集了 post 如下:

  {
    "author": "Rothfuss",
    "text": "Name of the Wind",
    "likes": 1007,
    "date": ISODate("2013-03-20T11:30:05Z")
  },
  {
    "author": "Rothfuss",
    "text": "Doors of Stone",
    "likes": 1,
    "date": ISODate("2051-03-20T11:30:05Z")
  }

我想获得每个作者的 post 和 his/her 最后一个 post 的计数。 同一个问题 here 有 SQL 个答案。我试图找到它的 MongoDB 替代品。

到目前为止我结束了这个查询:

db.collection.aggregate([
  {
    "$group": {
      "_id": "$author",
      "count": {
        "$sum": 1
      },
      "lastPost": {
        "$max": {
          "_id": "$date",
          "post": "$text"
        }
      }
    }
  }
])

这似乎可行,但不同的运行会产生不同的结果。可以在 Mongo playground 中测试 here。 我不明白如何从包含最大值的文档中使用 $max 到 select 另一个 属性。我是 MongoDB 的新手,因此非常感谢描述基础知识。

追加问题

是否可以限制 $sum 仅添加 post 且 likes 超过 100 个?

我觉得你的查询没问题,添加 $match 阶段可以过滤掉 likes > 100 的帖子。(你也可以在 $sum 中使用 $cond 但这里不需要)

查询

  • $max 累加器也可以用于文档 Here you can see how MongoDB compares documents
  • mongoplayground 有问题并且丢失了文档中字段的顺序(表现得好像它们是 hashmaps 而不是)(也在你的驱动程序中测试它)

Test code here

db.collection.aggregate([
  {
    "$match": {
      "likes": {
        "$gt": 100
      }
    }
  },
  {
    "$group": {
      "_id": "$author",
      "count": {
        "$sum": 1
      },
      "lastPost": {
        "$max": {
          _id: "$date",
          post: "$text"
        }
      }
    }
  }
])

its different runs generate different results.
I don't understand how to use $max to select another property from the document containing the maximum.

$max在多个字段中无效,并且在具有text/string值的字段中无效。

它将 select 一组 post 中的任何属性,每次都会不同。

所以准确的结果你可以在$group阶段之前添加新的阶段$sort,按日期降序排列,在小组阶段你可以select一个值$first 运算符,

  { $sort: { date: -1 } },
  {
    $group: {
      _id: "$author",
      count: { $sum: 1 },
      date: { $first: "$date" },
      post: { $first: "$text" }
    }
  }

Is it possible to limit $sum to only add posts with likes more than 100?

你的要求有两种含义,我不确定你问的是哪一种,但让我给出两种解决方案,

  1. 如果你只是不想计算 count 中的 post,但你想把它作为最后一个 post 的 datetext 如果是。
  • $cond 检查条件如果 likes 大于 100 则计数 1 否则计数 0
db.collection.aggregate([
  { $sort: { date: -1 } },
  {
    $group: {
      _id: "$author",
      count: {
        $sum: {
          $cond: [{ $gt: ["$likes", 100] }, 1, 0]
        }
      },
      date: { $first: "$date" },
      post: { $first: "$text" }
    }
  }
])

Playground

  1. 如果你不想数也不想最后一个post如果是的话。
  • 您可以在第一阶段添加一个 $match 阶段来检查大于条件,您的最终查询将是,
db.collection.aggregate([
  { $match: { likes: { $gt: 100 } } },
  { $sort: { date: -1 } },
  {
    $group: {
      _id: "$author",
      count: { $sum: 1 },
      date: { $first: "$date" },
      post: { $first: "$text" }
    }
  }
])

Playground