gpt4 book ai didi

javascript - 根据字段数组大小分组并删除文档

转载 作者:行者123 更新时间:2023-11-30 10:12:42 26 4
gpt4 key购买 nike

我有这样的文档:

{
"_id" : ObjectId("53bcedc39c837bba3e1bf1c2"),
id : "abc1",
someArray: [ 1 , 10 , 11]
}

{
"_id" : ObjectId("53bcedc39c837bba3e1bf1c4"),
id : "abc1",
someArray: [ 1 , 10]
}
... other similar documents with different Ids

我想遍历整个集合并删除 someArray 最小的文档,按 id 分组。因此,在此示例中,我按 abc1 分组(我得到 2 个文档),然后第二个文档将被删除,因为它在 someArray 中的计数最少。

没有 $count 累加器,所以我不知道如何使用 $group

此外,会有 1000 多个 ID 像这样重复,所以如果有批量检查/删除之类的东西就好了(可能是个愚蠢的问题,抱歉,Mongo 对我来说是全新的!)

最佳答案

删除“重复项”在这里是一个过程,没有简单的方法可以同时“识别”重复项并将它们作为单个语句“删除”。这里的另一个特殊之处是,查询表单不能“通常”确定数组的大小,当然也不能按文档中不存在的数组大小进行排序。

所有情况基本上归结为

  1. 识别“重复”的文档列表,然后理想地指出您要删除的特定文档,或者更确切地说是您“不想”从可能的重复项中删除的文档。

  2. 处理该列表以实际执行删除。

考虑到这一点,您希望拥有 2.6 或更高版本的现代 MongoDB,您可以从中获得游标 aggregate方法。你还想要 Bulk Operations API可在这些版本中获得最佳速度:

var bulk = db.collection.initializeOrderedBulkOp();
var counter = 0;

db.collection.aggregate([
{ "$project": {
"id": 1,
"size": { "$size": "$someArray" }
}},
{ "$sort": { "id": 1, "size": -1 } },
{ "$group": {
"_id": "$id",
"docId": { "$first": "$_id" }
}}
]).forEach(function(doc) {
bulk.find({ "id": doc._id, "_id": { "$ne": doc.docId }).remove();
counter++;

// Send to server once every 1000 statements only
if ( counter % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp(); // need to reset
}
});

// Clean up results that did not round to 1000
if ( counter % 1000 != 0 )
bulk.execute();

您仍然可以使用旧版本的 MongoDB 做很多相同的事情,但是 .aggregate() 的结果必须小于 16MB,这是 BSON 的限制。那仍然应该很多,但是对于旧版本,您还可以使用 mapReduce 输出到集合。

但是对于一般的聚合响应,您会得到一个结果数组,而且您也没有其他方便的方法来查找数组的大小。所以还有一点工作:

var result = db.collection.aggregate([
{ "$unwind": "$someArray" },
{ "$group": {
"_id": "$id",
"id": { "$first": "$id" },
"size": { "$sum": 1 }
}},
{ "$sort": { "id": 1, "size": -1 } },
{ "$group": {
"_id": "$id",
"docId": { "$first": "$_id" }
}}
]);

result.result.forEach(function(doc) {
db.collection.remove({ "id": doc._id, "_id": { "$ne": doc.docId } });
});

因此没有针对大型结果的游标,也没有批量操作,因此每个“删除”都需要单独发送到服务器。

所以在 MongoDB 中没有“子查询”,甚至当有超过“两个重复项”时,也没有一种方法可以从其他重复项中挑出您不想删除的文档。但这是执行此操作的一般方法。

请注意,如果出于“排序”之类的目的,数组的“大小”对您来说很重要,那么您最好的方法是将该“大小”保留为文档的另一个属性,以便使这些操作更轻松,无需像此处那样“计算”。

关于javascript - 根据字段数组大小分组并删除文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25601985/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com