MongoDB: 在单次更新中$push多个对象和$pop多个对象

7
假设有一个包含100个对象的MongoDB文档,我们想要保持数组长度固定为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从后面删除相同数量的对象?请注意,保留HTML标记。
2个回答

7
答案有点复杂,可以说是“是”和“否”。在单个更新中,您不能同时对同一数组执行$push$pull操作。这是因为在当前更新语法中,$push$pull都没有确定发生的顺序,所以不允许在“相同路径”的操作上执行这两个操作。
但是,在您的特定情况下,这不是您要问的问题。为了实现您想要的效果,MongoDB支持$slice修饰符,该修饰符可以与$each一起使用。这将有效地“限制”添加到数组中的新项的总大小。
根据您的示例:
Collection.update(
    { "exchange": "The Exchange", "market": "The Market" },
    { "$push": { "data": { "$each": newData, "$slice": 100 } } }
)

那实际上限制了数组的大小为前100个成员,同时向其中添加新项。
但需要注意的是,Meteor 实现的“minimongo”客户端版本可能不支持此操作。不过,您可以在服务器上执行此操作,并通过发布公开该方法。有很多示例可以向您展示如何使用发布。

6

3
再次用打字回答你的问题。需要注意的是,在JavaScript和MongoDB的"slice"操作中,负数表示从数组末尾开始计算。 - Neil Lunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接