从文档数组中删除最旧的N个元素

时间:2017-05-05 17:52:09

标签: arrays mongodb

我的mongodb中有一个包含非常大的数组(大约10k项)的文档。我试图只保留阵列中最新的1k(因此删除前9k元素)。该文件看起来像这样:

    {
        "_id" : 'fakeid64',
        "Dropper" : [
            {
                "md5" : "fakemd5-1"
            },
            {
                "md5" : "fakemd5-2"
            },
            ...,
            {
                "md5": "fakemd5-10000"
            }
        ]
    }

我如何做到这一点?

3 个答案:

答案 0 :(得分:1)

您可以使用$pullAll运算符 假设您使用python / pymongo驱动程序:

db.yourcollection.update(
  { _id: 'fakeid64'}, 
  {$pullAll: {'Dropper': db.yourcollection.findOne({'_id' : 'fakeid64'})['Dropper'].slice(0,9000)}}
)

或在mongo shell中:

String

(*)说如果你不允许你的文件在第一时间增长那么会好得多

答案 1 :(得分:0)

这只是查询的表示。基本上你可以使用限制和跳过来放松,然后使用光标foreach删除下面的项目:

db.your_collection.aggregate([
    { $match : { _id : 'fakeid64' } },
    { $unwind : "$Dropper"},
    { $skip : 1000},
    { $limit : 9000}
]).forEach(function(doc){
    db.your_collection.update({ _id : doc._id}, { $pull : { Dropper : doc.Dropper} }); 
});

答案 2 :(得分:0)

在此处执行的正确操作实际上涉及使用$push$each修饰符的$slice运算符。最初使用可能会违反直觉,您可以使用$push来删除"数组中的项目,但是当您看到预期的操作时,实际的用例是明确的。

db.collection.update(
  { "_id": "fakeid64" },
  { "$push": { "Dropper": { "$each": [], "$slice": -1000 } }
)

事实上,您可以按以下方式运行整个集合:

db.collection.update(
  { },
  { "$push": { "Dropper": { "$each": [], "$slice": -1000 } },
  { "multi": true }
)

这里发生的是$each的修饰符将一系列项目带到"添加"在$push操作中,在这种情况下,我们留空,因为我们实际上并不想添加任何内容。 $slice修饰符给出了"否定"价值实际上是说保持"最后n"在执行更新时,数组中存在元素,这正是您所要求的。

将军"意图"案例是在向"维护"添加新元素时使用$slice。数组在"最大值"给定长度,在这种情况下为1000.因此,您通常会与实际使用#34;添加"像这样的新项目:

db.collection.update(
  { "_id": "fakeid64" },
  { "$push": { "Dropper": { "$each": [{ "md5": "fakemd5-newEntry"}], "$slice": -1000 } }
)

这将追加$each中提供的新项目,同时还删除" start"中的所有项目。添加的总长度大于1000的阵列。

其他地方的说法不正确,您将$pullAll与文档中已存在的数组内容的提供列表一起使用,但该操作实际上是对数据库的两个请求。

误解是请求以" one"发送,但它实际上不是,并且基本上被解释为更长的形式(正确使用.slice()):

var md5s = db.collection.findOne({ "_id": "fakeid64" }).Dropper.slice(-1000);

db.collection.update(
  { "_id": "fakeid64" },
  { "$pullAll": { "Dropper": md5s } }
)

因此,当您考虑到文档中数组的状态时,您可以看到这不是非常有效并且实际上非常危险 可能会改变"读"数组内容和实际的#34;写"更新操作,因为它们是分开发生的。

这就是为什么MongoDB具有$push $slice的原子运算符,正如所展示的那样。因为它不仅更有效率,而且还考虑到实际的状态"在实际修改发生时修改的文件。