聚合错误:$ arrayElemAt的第一个参数必须是数组,但是对象

时间:2019-03-21 15:05:22

标签: mongodb mongoose aggregation-framework

我正在尝试使用以下管道在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阶段,但错误消失了,但是没有应用时间范围

1 个答案:

答案 0 :(得分:0)

我相信您缺少一个$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] }
  }}
])