【问题标题】:Aggregation error: $arrayElemAt's first argument must be an array, but is object聚合错误:$arrayElemAt 的第一个参数必须是数组,但是是对象
【发布时间】:2019-03-21 15:05:22
【问题描述】:

我正在尝试使用以下管道在 mongo 中聚合一个集合:

  const results = await Price.aggregate([
    { $match: { date: today } },
    { $unwind: '$points' },
    { $match: { 'points.time': { $gte: start, $lte: now } } },
    { $sort: { 'points.time': 1 } },
    { $project: {
      'high': { $max: '$points.price' },
      'low': { $min: '$points.price' },
      'open': { $arrayElemAt: ['$points', 0] },
      'close': { $arrayElemAt: ['$points', -1] }
    } }
  ])

但是$arrayElemAt 运算符可能无法正常工作,因为前面的阶段之一(我相信$unwind)将我在文档中的点数组转换为对象。我该如何解决这个问题?

示例文档:

{
    "_id" : ObjectId("5c93ac3ab89045027259a23f"),
    "date" : ISODate("2019-03-21T00:00:00Z"),
    "symbol" : "CC6P",
    "points" : [
        {
            "_id" : ObjectId("5c93ac3ab89045027259a244"),
            "volume" : 553,
            "time" : ISODate("2019-03-21T09:35:34.239Z"),
            "price" : 71
        },
        {
            "_id" : ObjectId("5c93ac3ab89045027259a243"),
            "volume" : 1736,
            "time" : ISODate("2019-03-21T09:57:34.239Z"),
            "price" : 49
        },
      ....
    ],

我的预期结果是一个对象数组,其中应该传递给项目阶段的点应该是第二个$match 中指定范围内的点。我尝试合并两个$match 阶段并删除$unwind 阶段,错误消失了,但是没有应用时间范围

【问题讨论】:

  • 您在第二阶段有$unwinded points 数组。除非您不显示一些示例文档和您期望的结果,否则不能说。
  • @anthonywinzlet 已编辑问题

标签: mongodb mongoose aggregation-framework


【解决方案1】:

我相信您缺少一个 $group 阶段来回滚您的 points 数组

const results = await Price.aggregate([
  { "$match": { "date": today } },
  { "$unwind": "$points" },
  { "$match": { "points.time": { "$gte": start, "$lte": now } } },
  { "$sort": { "points.time": 1 } },
  { "$group": {
    "_id": "$_id",
    "points": { "$push": "$points" },
    "date": { "$first": "$date" },
    "symbol": { "$first": "$symbol" }
  }},
  { "$project": {
    "high": { "$max": "$points.price" },
    "low": { "$min": "$points.price" },
    "open": { "$arrayElemAt": ["$points", 0] },
    "close": { "$arrayElemAt": ["$points", -1] }
  }}
])

【讨论】:

  • 我一开始做放松的唯一原因是做第二场比赛。我可以以某种方式避免第一和第二比赛阶段吗?此外,您在小组赛阶段缺少两个逗号。
  • 顺便说一句,这很好用,我只是想知道是否有更好的方法来做到这一点,因为它将在大量数据上执行。
  • 是的,无需使用$unwind 即可完成。请等待我正在编辑我的答案
  • 更新了我的答案
  • 您删除了排序阶段?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 2019-03-27
  • 2014-12-11
  • 1970-01-01
相关资源
最近更新 更多