比较两个集合上的mongo diff

时间:2016-12-19 12:39:24

标签: mongodb

我有两个mongo集合,一个是生产环境,另一个是测试环境。我如何比较其中两个之间的差异?我尝试将它们转储到bson然后转换为json。但我不能对它们执行简单的差异,因为排序可能会有所不同,而且json文件太大而无法排序。

7 个答案:

答案 0 :(得分:9)

在shell中尝试以下操作,它将迭代集合中的每个项目,并尝试根据ID匹配每个文档。

假设我们有2个集ValidationAttributedb.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的字段,其值是文档所来自的集合(testprod),按顺序,当我们合并两个集合时,跟踪文档的来源。
  • $project为其字段doc(其值是文档本身)(由于$$ROOT变量)。此字段将用于一起$group个文档。
  • $unionWith prod集合,以便将两个集合中的文档合并到同一聚合管道中。 pipeline参数是一个可选的聚合管道,应用于将文档插入下游管道之前要合并的集合(prod)中的文档。而且我们将应用与$unset个文档相同的$project / test阶段。
  • $group的{​​{1}}和test文档基于我们创建的代表实际文档的prod字段。然后,我们将两个字段doctest累积为源自一个或另一个集合(通过prod(如果为表达式)的分组文档的$sum(计数))。
  • $cond通过仅保留不具有相同数量的test和prod文档数量的结果分组元素:两个集合之间的实际差异。

答案 2 :(得分:3)

dbHash已经成功了:

use db_name
db.runCommand('dbHash')

它返回每个集合的哈希值。然后你可以比较它们。这很准确。

答案 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