从MongoDB中删除与数组中包含的属性值相同的文档

从MongoDB中删除与数组中包含的属性值相同的文档,mongodb,mongodb-query,Mongodb,Mongodb Query,我正在努力从MongoDB 3.0数据库中删除共享两个属性值profiles.platform和profiles.handle的文档 { _id: ID profiles: [{ source: {}, isProfile: Boolean, profile: {}, demographics: { male: Number, female: Number

我正在努力从MongoDB 3.0数据库中删除共享两个属性值
profiles.platform
profiles.handle
的文档

{
    _id: ID
    profiles: [{
        source: {},
        isProfile: Boolean,
        profile: {},
        demographics: {
            male: Number,
            female: Number
        },
        handle: String,
        platform: String
    }]
}
我尝试使用聚合框架获取共享这些属性值的文档的_id

db.collection.aggregate([{
    "$group": {
        "_id": "$id",
        "duplicates": {
            "$addToSet": "$_id"
        },
        "handles": {
            "$addToSet": "$profiles.profile.handle",
            "$addToSet": "$profiles.profile.platform"
        },
        "count": {
            "$sum": 1
        }
    }
}, {
    "$match": {
        "count": {
            "$gt": 1
        }
    }
}, {
    "$out": "dupes"
}])
但这并不奏效。我犯了个错误

{
    "errmsg": "exception: insert for $out failed: { lastOp: Timestamp 1433113685000|1, connectionId: 4856701, err: \"BSONObj size: 56348873 (0x35BD0C9) is invalid. Size must be between 0 and 16793600(16MB) First element: _id: null\", code: 10334, n: 0, ok: 1.0 }",
    "code": 16996,
    "ok": 0
}
重复文档的示例
文件1

{
    _id: ID
    profiles: [{
        source: {},
        isProfile: true,
        profile: {},
        demographics: {
            male: 1,
            female: 0
        },
        handle:'tom', <--- specific property that is duplicated.
        platform:'myspace' <--- specific property that is duplicated.
    }]
}
{
_id:id
简介:[{
资料来源:{},
isProfile:是的,
档案:{},
人口统计:{
男:1,,
女:0
},

handle:'tom',删除恰好包含具有特定属性的数组项的文档,并将另一个文档与具有这些属性的共享数组项相匹配,这不是一个简单的操作

可能最好结合使用聚合框架和单独的批量写入操作来实现这一点

var bulk=db.collection.initializeOrderedBulkOp(),
计数=0;
db.collection.aggregate([
//展开阵列
{“$unwind”:“$profiles”},
//按所需键分组并计数
{“$组”:{
“_id”:{
“句柄”:“$profiles.handle”,
“平台”:“$profiles.platform”
},
“计数”:{“$sum”:1}
“id”:{“$addToSet”:“$\u id”}
}},
//过滤任何不重复的内容
{“$match”:{“count”:{“$gt”:1}}},
]).forEach(功能(文档){
doc.ids.shift();//删除要保留的第一项
bulk.remove({“\u id”:{“$in”:doc.ids}});
计数++;
//每1000次仅执行一次并重新初始化
如果(计数%1000==0){
bulk.execute();
bulk=db.collecion.initializeOrderedBulkOp();
}
});
//清除任何排队的
如果(计数%1000!=0)
bulk.execute();
基本上,首先“识别”包含重复项的文档,然后“保留”一个文档,或者“排除”删除其中一个文档,然后对列表中的每个“重复项”处理
.remove()

您可以进一步通过额外的“重复消除”文档本身来实现这一点,但这可能是一种相当安全的方法,因为几乎没有可能的额外开销

虽然方便,但我个人不会在这里使用
$out
,也不会尝试在聚合管道中完成所有工作。主要原因是将整个文档“保留”在这样的分组中可能会超出16MB BSON限制,而且尝试“标记”重复条目并仅保留一个条目也会带来大量开销


如果您有
$out
,那么您的MongoDB也支持批量操作,因此最好使用它们来减少流量。

尝试删除“句柄…”查询的一部分。您达到了Mongo的16MB文档限制。这不起作用。MongoDB有大约200万条记录。实际上,您正在带回每个文档。您按id进行分组,并且是唯一的。您想按profile.profile.handle和/或profile.profile.profile进行分组。您能举一个重复的d的示例吗文档?我明白了。但我一直在寻找复制的特定属性。听起来你需要$unwind你的配置文件数组并在profiles.profile.handle或profiles.profile.platform上分组。你可能需要分两步完成。我在这里看到的“不清楚”是你要求从“数组内”删除“重复项”在每个文档中或在不同的文档中,“可能”在其中一个数组项中是否具有相同的属性?那么需要删除什么?文档还是文档中的数组项?
{
    _id: ID
    profiles: [{
        source: {},
        isProfile: true,
        profile: {},
        demographics: {
            male: 1,
            female: 0
        },
        handle:'tom', <--- specific property that is duplicated.
        platform:'myspace' <--- specific property that is duplicated.
    }]
}