MongoDB: $push 多个对象,$pop 多个对象单次更新

MongoDB: $push Multiple Objects, and $pop Multiple Objects in Single Update

想象一个 MongoDB 包含 100 个对象的数组的文档。我们希望将数组长度 固定 100。当一批新对象到达时(可能是 1、5、10 等),我们希望用新对象更新数组,同时删除等量的旧对象,以便数组长度保持固定。我选择从 MongoDB 读取数组到我的应用程序中,进行一些修改,然后使用 $set 更新数组:

var newData = [
  { ... },
  { ... },
  { ... },
  { ... },
  { ... }
];
var oldData = Collection.findOne({exchange: 'The Exchange', market: 'The Market'}).data;
newData = newData.concat(oldData).slice(0, 100);
Collection.update(
  {
    exchange: 'The Exchange',
    market: 'The Market'
  },
  {
    $set: {
      data: newData
    }
  }

是否可以在 MongoDB 到 $push 中将新的放在前面,同时使用 $pop 从后面删除等量的对象?

Is it possible in MongoDB to $push the new on to the front, while simultaneously using $pop to remove an equal amount of objects off the back?

是的,使用 $slice:

$push: {
    data: {
       $each: [ { ... }, { ... } ], // your batch
       $slice: -100 // maximum array size
    }
 }

有关示例,请参阅 http://docs.mongodb.org/manual/tutorial/limit-number-of-elements-in-updated-array/

嗯,答案是 "yes" 和 "no",用稍微有点混乱的术语来说。你不能做的是在单一更新中对同一个数组进行 $push and $pull 操作。这对于 "same path" 操作是不允许的,因为 $push$pull 都没有真正确定在当前更新语法中以任何顺序发生。

但是在您的特定上下文中,这不是您要问的。为所欲为,MongoDB支持$slice modifier which can be used along with $each。这将有效地 "limit" 数组的总大小,因为新项目被添加到它。

按照你的例子:

Collection.update(
    { "exchange": "The Exchange", "market": "The Market" },
    { "$push": { "data": { "$each": newData, "$slice": 100 } } }
)

这有效地将数组的大小限制为前 100 个成员,同时向其中添加新项。

请注意,这在由 meteor 实现的 "minimongo" 客户端版本中可能不受支持。你可以做的是在服务器上执行它,并通过发布公开该方法。有很多示例可以向您展示如何使用发布。