Mongodb转储(筛选文档和字段)

Mongodb转储(筛选文档和字段),mongodb,filter,dump,bson,mongoexport,Mongodb,Filter,Dump,Bson,Mongoexport,我想对Mongodb数据库进行部分转储(部分如中所示,我需要过滤一些文档和一些字段)。然后,此转储将导入到另一台服务器上 我无法使用mongodump实用程序,因为它不允许筛选字段。 我可以使用mongoexport实用程序,因为它可以过滤文档和字段。但是,文档说明mongoexport只能输出JSON文件,并且: 无法可靠地保留所有丰富的BSON数据类型,因为JSON只能表示BSON支持的类型的子集 我觉得这句话有点含糊,我不完全理解。那么,如果我用JSON转储数据库,会发生什么呢?我要冒什么

我想对Mongodb数据库进行部分转储(部分如中所示,我需要过滤一些文档和一些字段)。然后,此转储将导入到另一台服务器上

我无法使用mongodump实用程序,因为它不允许筛选字段。
我可以使用mongoexport实用程序,因为它可以过滤文档和字段。但是,文档说明mongoexport只能输出JSON文件,并且:

无法可靠地保留所有丰富的BSON数据类型,因为JSON只能表示BSON支持的类型的子集

  • 我觉得这句话有点含糊,我不完全理解。那么,如果我用JSON转储数据库,会发生什么呢?我要冒什么风险?我有可能丢失一些文件吗
  • 如果您认为我应该绝对避免在生产中使用mongoexport,那么我可以编写自己的Nodejs应用程序来进行过滤并在BSON中输出转储吗?或者这是不可能的

  • 可以使用,而无需编写底层实现来读取和编写BSON内容。甚至在使用JSON格式时,也有一些选项实际上保留了类型,而您甚至不需要一个“视图”

    mongodump一起使用视图
    基本前提是创建一个只返回所需内容的视图。视图可以是任何聚合管道表达式的结果

    例如,给定集合中的一个简单文档:

    db.test.insert({ "a": 1, "b": 2, "c": 3 })
    
    您可以使用所需字段在该集合上创建视图:

    db.test.createView("testView", "test", [{ "$project": { "a": 1, "b": 2 } }])
    
    然后退出mongo shell,您可以使用以下选项访问视图:

    这仅导出命名的“集合”(实际上是一个视图)。这意味着它不只是返回视图定义(本质上是聚合管道),而是返回结果,就像它是一个真实的集合一样

    然后可以通过以下方式加载生成的BSON内容:

    然后,BSON转储中的内容实际写入到您所连接主机的新数据库目标中,并且使用指定的集合名称

    use other
    db.test.find()
    
    { "_id" : ObjectId("5bfb3e0eadd1d8af906ad140"), "a" : 1, "b" : 2 }
    
    还需要注意的是,聚合管道实际上可以是任何东西,因此
    $match
    语句可以进行过滤,您可以根据需要进行转换甚至实际“聚合”

    将视图或
    --字段
    mongoexport
    同样,该实用程序也可以从视图访问内容

    尽管这不是“严格的BSON”,但MongoDB实际上有一个标准,它确实保留了数据类型。这实际上包含在下的文档中

    因此,这不是二进制格式,与JSON一样,它确实占用了相当多的存储空间,但必要的信息确实存在

    例如:

    db.mixed.insert({
      "a": NumberLong(1),
      "b": NumberDecimal("123.45"),
      "c": new Date(),
      "d":  "unwanted"
    })
    
    mongo
    shell中显示为:

    {
            "_id" : ObjectId("5bfb428790b2b4e4241a015c"),
            "a" : NumberLong(1),
            "b" : NumberDecimal("123.45"),
            "c" : ISODate("2018-11-26T00:47:03.033Z"),
            "d" : "unwanted"
    }
    
    您仍然可以设置视图:

    db.createView("mixedView", "mixed", [{ "$project": { "a": 1, "b": 1, "c": 1 } }])
    
    导出将只拾取数据:

    mongoexport --db test --collection mixedView > out.json
    
    {
            "_id": {
                    "$oid": "5bfb428790b2b4e4241a015c"
            },
            "a": {
                    "$numberLong": "1"
            },
            "b": {
                    "$numberDecimal": "123.45"
            },
            "c": {
                    "$date": "2018-11-26T00:47:03.033Z"
            }
    }
    
    use other
    db.mixed.findOne()
    {
            "_id" : ObjectId("5bfb428790b2b4e4241a015c"),
            "a" : NumberLong(1),
            "b" : NumberDecimal("123.45"),
            "c" : ISODate("2018-11-26T00:47:03.033Z")
    }
    
    或在原始收藏中使用相同的内容,仅用于选择:

    mongoexport --db test --collection mixed --fields a,b,c > out.json
    
    输出完全相同。唯一的限制是,只能支持给定给
    find()
    或类似对象的正则查询表达式。这不如a灵活,但可以对大多数需求进行基本过滤

    格式由识别,许多语言也有解析器的实现,可以识别这种格式,在读取内容时,会将内容插入目标集合,并保留“类型”信息:

    mongoimport --db other --collection mixed out.json
    
    然后查看数据:

    mongoexport --db test --collection mixedView > out.json
    
    {
            "_id": {
                    "$oid": "5bfb428790b2b4e4241a015c"
            },
            "a": {
                    "$numberLong": "1"
            },
            "b": {
                    "$numberDecimal": "123.45"
            },
            "c": {
                    "$date": "2018-11-26T00:47:03.033Z"
            }
    }
    
    use other
    db.mixed.findOne()
    {
            "_id" : ObjectId("5bfb428790b2b4e4241a015c"),
            "a" : NumberLong(1),
            "b" : NumberDecimal("123.45"),
            "c" : ISODate("2018-11-26T00:47:03.033Z")
    }
    
    因此,在发送二进制内容可能不可行或甚至不可取的情况下,为了数据交换的目的而存在这种格式是可能的,但维护“类型”信息是可取的


    总的来说,您可以使用许多选项,而无需恢复到读取和写入二进制BSON格式,或任何其他复杂的二进制格式来存储传输之间的数据


    作为“模糊”一段的注释,文档页面中列出了实际支持的BSON类型。您甚至可以将此与进行比较,以发现尽管有“谨慎”的声明,但实际上您将使用的常见类型的数据都得到了支持。虽然该规范的一些外部解释可能无法理解所有这些,但捆绑的实用程序,如
    mongoexport
    mongoimport
    确实符合要求。

    感谢您的详细解释。所以,如果我错了,请纠正我的错误,但我的第一个问题的答案是,不,我不会因为使用JSON而丢失任何信息,因为正如您所说的“这不是二进制格式,而JSON确实占用了相当多的存储空间,但必要的信息确实存在”。这意味着JSON转储文件包含完全相同的信息,但它通过占用更多空间对其进行编码。所以我可以期望JSON转储文件比其BSON等效转储文件大,对吗?至于我的第二个问题:是否可以编写自己的Nodejs应用程序来进行过滤并在BSON中输出转储文件?现在我将使用您的解决方案(即创建一个视图,然后使用mongodump转储它),但我仍然有兴趣知道是否可以使用定制的Nodejs应用程序来代替。这样做的原因是性能在我的场景中非常重要,我感觉创建一个视图并随后使用mongodump将其转储将比执行一个Nodejs应用程序(该应用程序过滤数据并自动将其写入(BSON)转储文件)所需的时间要长得多。