我有两个mongo集合,一个是生产环境,另一个是测试环境。我如何比较其中两个之间的差异?我尝试将它们转储到bson然后转换为json。但我不能对它们执行简单的差异,因为排序可能会有所不同,而且json文件太大而无法排序。
答案 0 :(得分:9)
在shell中尝试以下操作,它将迭代集合中的每个项目,并尝试根据ID匹配每个文档。
假设我们有2个集ValidationAttribute
和db.col1
:
db.col2
然后我们可以创建一个javascript函数来比较2个集合
> db.col1.find()
{ "_id" : 1, "item" : 1 }
{ "_id" : 2, "item" : 2 }
{ "_id" : 3, "item" : 3 }
{ "_id" : 4, "item" : 4 }
> db.col2.find()
{ "_id" : 1, "item" : 1 }
{ "_id" : 2, "item" : 2 }
{ "_id" : 3, "item" : 3 }
{ "_id" : 4, "item" : 4 }
然后打电话如下:
function compareCollection(col1, col2){
if(col1.count() !== col2.count()){
return false;
}
var same = true;
var compared = col1.find().forEach(function(doc1){
var doc2 = col2.findOne({_id: doc1._id});
same = same && JSON.stringify(doc1)==JSON.stringify(doc2);
});
return same;
}
如果我们有第3个集合> compareCollection(db.col1, db.col2)
true
db.col3
并比较这个
> db.col3.find()
{ "_id" : 1, "item" : 1 }
我们会得到预期的结果。
如果我们还有第4个集合,其中包含匹配的文档但不同的数据> compareCollection(db.col1, db.col3)
false
db.col4
这也将返回> db.col4.find()
{ "_id" : 1, "item" : 10 }
{ "_id" : 2, "item" : 2 }
{ "_id" : 3, "item" : 3 }
{ "_id" : 4, "item" : 4 }
false
答案 1 :(得分:5)
从Mongo 4.4
开始,聚合框架提供了一个新的$unionWith
阶段,执行两个集合的联合(将两个集合的合并管道结果合并为一个结果集)。
使查找两个集合之间的差异更加容易:
// > db.test.find()
// { "a" : 9, "b" : 2 }
// { "a" : 4, "b" : 12 }
// { "a" : 3, "b" : 5 }
// { "a" : 0, "b" : 7 }
// { "a" : 7, "b" : 12 }
// > db.prod.find()
// { "a" : 3, "b" : 5 }
// { "a" : 4, "b" : 12 }
// { "a" : 3, "b" : 5 }
// { "a" : 0, "b" : 7 }
db.test.aggregate(
{ $unset: "_id" },
{ $project: { from: "test", doc: "$$ROOT" } },
{ $unionWith: {
coll: "prod",
pipeline: [
{ $unset: "_id" },
{ $project: { from: "prod", doc: "$$ROOT" } }
]
}},
{ $group: {
_id: "$doc",
test: { $sum: { $cond: [ { $eq: ["$from", "test"] }, 1, 0 ] } },
prod: { $sum: { $cond: [ { $eq: ["$from", "prod"] }, 1, 0 ] } }
}},
{ $match: { $expr: { $ne: ["$test", "$prod"] } } }
)
// { "_id" : { "a" : 7, "b" : 12 }, "test" : 1, "prod" : 0 }
// { "_id" : { "a" : 9, "b" : 2 }, "test" : 1, "prod" : 0 }
// { "_id" : { "a" : 3, "b" : 5 }, "test" : 1, "prod" : 2 }
此:
$unset
使用_id
,以便后者能够自己$group
编写文档而无需考虑_id
(因为在其他集合中可能有所不同)。 $project
是字段from
的字段,其值是文档所来自的集合(test
或prod
),按顺序,当我们合并两个集合时,跟踪文档的来源。$project
为其字段doc
(其值是文档本身)(由于$$ROOT
变量)。此字段将用于一起$group
个文档。$unionWith
prod
集合,以便将两个集合中的文档合并到同一聚合管道中。 pipeline
参数是一个可选的聚合管道,应用于将文档插入下游管道之前要合并的集合(prod
)中的文档。而且我们将应用与$unset
个文档相同的$project
/ test
阶段。$group
的{{1}}和test
文档基于我们创建的代表实际文档的prod
字段。然后,我们将两个字段doc
和test
累积为源自一个或另一个集合(通过prod
(如果为表达式)的分组文档的$sum
(计数))。$cond
通过仅保留不具有相同数量的test和prod文档数量的结果分组元素:两个集合之间的实际差异。答案 2 :(得分:3)
答案 3 :(得分:2)
使用Kevin Smith response,我有一个新版本,仅用于比较并返回collectionB
没有与collectionA
进行比较的ID。当你有很多记录时,将结果保存在collectionC
。
db.collectionA.find().forEach(function(doc1){
var doc2 = db.collectionB.findOne({_id: doc1._id});
if (!(doc2)) {
db.collectionC.insert(doc1);
}
});
答案 4 :(得分:1)
如果您只需要比较字段的子集(例如,您不需要比较ID),则可以通过以下方式执行此操作。将集合导出到csv,指定要比较的字段(source):
mongoexport -d <db_name> -c <col_name> --fields "field1,field2" --type=csv | sort > export.csv
然后在csv文件上执行简单的diff
。请注意,csv文件中的列顺序对应于--field
选项。
优点:
缺点:
mongoexport
可能会很慢。要获取集合中所有文档中的所有字段,请参阅this answer。
答案 5 :(得分:0)
使用Studio 3T来比较mongodb。 您还可以比较集合,数据库,单个记录。 只需要下载并连接mongo。 这是下载链接https://studio3t.com/
答案 6 :(得分:0)
mongoexport
现在有一个--sort
选项:
例如:
$ mongo
test> db.coll.insertMany([
{ _id: 0, name: 'Alex' },
{ _id: 1, name: 'Bart' },
{ _id: 2, name: 'Maria' },
{ _id: 3, name: 'Aristotle' },
]);
{
"acknowledged": true,
"insertedIds": [
0,
1,
2,
3
]
}
导出:
mongoexport -d test -c coll --sort "{name: 1}"
2018-10-25T15:50:07.210+0300 connected to: localhost
{"_id":0.0,"name":"Alex"}
{"_id":3.0,"name":"Aristotle"}
{"_id":1.0,"name":"Bart"}
{"_id":2.0,"name":"Maria"}
2018-10-25T15:50:07.210+0300 exported 4 records
mongoexport -d test -c coll --sort "{name: -1}"
2018-10-25T15:49:42.010+0300 connected to: localhost
{"_id":2.0,"name":"Maria"}
{"_id":1.0,"name":"Bart"}
{"_id":3.0,"name":"Aristotle"}
{"_id":0.0,"name":"Alex"}
2018-10-25T15:49:42.011+0300 exported 4 records
导出集合后,您可以在命令行中执行diff
或使用Beyond Compare之类的图形用户界面(GUI)工具。
仅供参考:如果您的文档可能具有相同的数据,但具有不同的_id
值:
像这样导出时,您可以排除_id
字段:https://stackoverflow.com/a/49895549/728287