提问者:小点点

集合操作中的Mongo条件聚合


我试图用以下事务执行MongoDB记录的条件更新。

db.collection(SESSIONS_COLLECTION)
  .updateOne({_id: ObjectId(id)},
    {
      $set: {
        end: {
          $cond: {
            if: { $gt: ["$end", latestActionDate] }, then: "$end", else: latestActionDate
          }
        }
      },
      $push: {
        actions: {
          $each: data.map(action => ({
            ...action,
            time: new Date(action.time)
          }))
        }
      }
    }
  );

但我所有的努力都被粉碎了。 MongoError:'end.$cond'中的dollar($)前缀字段'$cond'对于存储无效。可能根本不允许这样的操作,但我更愿意认为我遗漏了一些东西。


共1个答案

匿名用户

问题是您将正常的更新操作与聚合运算符混在一起,要在更新中使用聚合运算符,您需要将更新部分包装在[]中,以说明它实际上是一个聚合管道。

启动MongoDB版本4.2时,可以使用聚合管道更新:

代码:

let actionArray = data.map((action) => ({
  ...action,
  time: new Date(action.time),
}));

db.collection(SESSIONS_COLLECTION).updateOne({ _id: ObjectId(id) }, [
  {
    $set: {
      end: {
        $cond: [{ $gt: ["$end", latestActionDate] }, "$end", latestActionDate]
      }
    }
  },  
  /** (fail safe stage) this second stage is optional but needed in general as `$push` will add a new array
   *  if that field doesn't exists earlier to update operation 
   * but `$concatArray` doesn't, So this helps to add `[]` prior to below step */
  {
    $set: { actions: { $ifNull: [ "$actions", [] ] } }
  },
  {
    $set: {
      actions: { $concatArrays: ["$actions", actionArray] }
    }
  }
]);

注意:

由于我们在这里使用聚合管道,您需要使用聚合运算符,而使用很少的查询/更新运算符是行不通的。