根据字段数组大小对文档进行分组和删除文档
group by and delete documents based on a field array size
我有这样的文档:
{
"_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对我来说都是新的!)
删除"重复项"在这里是一个过程,没有简单的方法可以将"识别"重复项和"删除"它们作为一个单独的语句。这里的另一个特殊之处是,查询表单"通常"不能确定数组的大小,当然也不能根据文档中尚未存在的数组进行排序。
所有案例基本上都归结为
-
识别"重复"的文档列表,然后理想情况下,用手指触摸要删除的特定文档,或者更多地触摸到你"不"想从可能的重复中删除的文档。
-
处理该列表以实际执行删除。
考虑到这一点,您希望有一个2.6或更高版本的现代MongoDB,在那里您可以从聚合方法中获得一个游标。您还希望批量操作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中没有"子查询",甚至当有超过"两个重复项"时,也没有从其他重复项中挑出您不想删除的文档的方法。但这是一般的方法
需要注意的是,如果数组的"大小"对于"排序"等目的来说很重要,那么最好的做法是将该"大小"保留为文档的另一个属性,这样就可以更容易地进行这些操作,而无需像这里所做的那样"计算"。
- 删除“;NaN”;来自HTML文档
- 如何筛选要写入新文档的HTML,删除JavaScript中的某些类和/或ID
- 从 MonogDB 中删除具有特定密钥计数的文档
- MongoDB 删除重复的子文档
- 如何使用文档的ID从mongoDB集合中删除文档
- 查找文档,然后在数组中查找条目并将其从数组中删除
- 如何删除MongoDB中的文档和所有嵌入文档
- 无论如何都要获取文档.在不删除整个页面的情况下写入即可工作
- 如何删除猫鼬中的特定子文档
- 可以't通过Express路由从Mongodb中删除文档
- 在文档中搜索文本以删除的文本超过找到它的标签
- 如何使用vanillaJS将mp4视频插入到具有特定维度的html文档中,播放2秒,然后删除节点
- 从Express,Node.js应用程序中删除MongoDB文档
- 使用 OR 条件删除带有猫鼬的 MongoDB 中的文档
- 如何删除创建的创建文档片段对象
- 如果当前日期>文档日期,如何删除文档
- 如何使用猫鼬从集合中删除所有文档
- 如何使用 ExtendScript 从 InDesign 文档的所有脚注引用中删除斜体和粗体样式
- JQuery 文档单击取消绑定将删除所有子单击事件
- j查询文档删除键