and*_*wrk 5 javascript mongodb mongodb-query aggregation-framework
我的数据如下:
{
"foo_list": [
{
"id": "98aa4987-d812-4aba-ac20-92d1079f87b2",
"name": "Foo 1",
"slug": "foo-1"
},
{
"id": "98aa4987-d812-4aba-ac20-92d1079f87b2",
"name": "Foo 1",
"slug": "foo-1"
},
{
"id": "157569ec-abab-4bfb-b732-55e9c8f4a57d",
"name": "Foo 3",
"slug": "foo-3"
}
]
}
Run Code Online (Sandbox Code Playgroud)
foo_list模型中的字段在哪里被称为Bar.请注意,数组中的第一个和第二个对象是完全重复的.
除了切换到PostgresSQL的明显解决方案之外,我可以运行哪些MongoDB查询来删除重复的条目foo_list?
类似的答案并没有完全削减它:
如果数组中有明显的字符串,这些问题就会回答这个问题.但是在我的情况下,数组中充满了对象.
我希望很明显我对查询数据库不感兴趣; 我希望重复项永远不会从数据库中消失.
Nei*_*unn 10
纯粹从聚合框架的角度来看,有一些方法可以做到这一点.
你可以$setUnion在现代版本中申请:
db.collection.aggregate([
{ "$project": {
"foo_list": { "$setUnion": [ "$foo_list", "$foo_list" ] }
}}
])
Run Code Online (Sandbox Code Playgroud)
db.collection.aggregate([
{ "$unwind": "$foo_list" },
{ "$group": {
"_id": "$_id",
"foo_list": { "$addToSet": "$foo_list" }
}}
])
Run Code Online (Sandbox Code Playgroud)
或者,如果您只是对重复项感兴趣,那么通过一般分组:
db.collection.aggregate([
{ "$unwind": "$foo_list" },
{ "$group": {
"_id": {
"_id": "$_id",
"foo_list": "$foo_list"
},
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$ne": 1 } } },
{ "$group": {
"_id": "$_id._id",
"foo_list": { "$push": "$_id.foo_list" }
}}
])
Run Code Online (Sandbox Code Playgroud)
如果您确实希望使用另一个更新语句从数据中"删除"重复项,则最后一个表单可能对您有用,因为它标识了重复的元素.
因此,在最后一种形式中,样本数据的返回结果标识了副本:
{
"_id" : ObjectId("53f5f7314ffa9b02cf01c076"),
"foo_list" : [
{
"id" : "98aa4987-d812-4aba-ac20-92d1079f87b2",
"name" : "Foo 1",
"slug" : "foo-1"
}
]
}
Run Code Online (Sandbox Code Playgroud)
每个文档从集合中返回结果,其中包含数组中的重复条目以及哪些条目是重复的.这是您需要更新的信息,您可以根据需要指定结果中的更新信息来循环结果,以便删除重复项.
这实际上是每个文档有两个更新语句,因为一个简单的$pull操作会删除"两个"项,这不是你想要的:
var cursor = db.collection.aggregate([
{ "$unwind": "$foo_list" },
{ "$group": {
"_id": {
"_id": "$_id",
"foo_list": "$foo_list"
},
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$ne": 1 } } },
{ "$group": {
"_id": "$_id._id",
"foo_list": { "$push": "$_id.foo_list" }
}}
])
var batch = db.collection.initializeOrderedBulkOp();
var count = 0;
cursor.forEach(function(doc) {
doc.foo_list.forEach(function(dup) {
batch.find({ "_id": doc._id, "foo_list": { "$elemMatch": dup } }).updateOne({
"$unset": { "foo_list.$": "" }
});
batch.find({ "_id": doc._id }).updateOne({
"$pull": { "foo_list": null }
});
]);
count++;
if ( count % 500 == 0 ) {
batch.execute();
batch = db.collection.initializeOrderedBulkOp();
}
});
if ( count % 500 != 0 )
batch.execute();
Run Code Online (Sandbox Code Playgroud)
这是现代MongoDB 2.6及以上的方法,其中游标来自聚合和Bulk操作以进行更新.但原则保持不变:
因此,在处理上述操作后,您的示例现在看起来像这样:
{
"_id" : ObjectId("53f5f7314ffa9b02cf01c076"),
"foo_list" : [
{
"id" : "98aa4987-d812-4aba-ac20-92d1079f87b2",
"name" : "Foo 1",
"slug" : "foo-1"
},
{
"id" : "157569ec-abab-4bfb-b732-55e9c8f4a57d",
"name" : "Foo 3",
"slug" : "foo-3"
}
]
}
Run Code Online (Sandbox Code Playgroud)
删除副本时"重复"项仍然完好无损.这就是您处理如何识别和删除集合中的重复数据的方法.
| 归档时间: |
|
| 查看次数: |
3656 次 |
| 最近记录: |