Mongodb转储(过滤文档和字段)

时间:2018-11-25 23:46:48

标签: mongodb filter dump bson mongoexport

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

我不能使用 mongodump 实用程序,因为它不允许过滤字段。
我可以使用 mongoexport 实用程序,因为它可以同时过滤文档和字段。不过,文档指出 mongoexport 只能输出JSON文件,并且:

  

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

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

1 个答案:

答案 0 :(得分:3)

可以使用Views进行操作,而不必诉诸于编写读写BSON内容的底层实现。实际上,即使使用JSON格式,也有一些选项保留类型,并且您甚至不需要“查看”。

通过mongodump使用视图

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

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

db.test.insert({ "a": 1, "b": 2, "c": 3 })

您可以在该集合上创建带有仅所需字段的视图:

db.test.createView("testView", "test", [{ "$project": { "a": 1, "b": 2 } }])

然后退出mongo shell,您可以使用mongodump选项从--viewsAsCollections访问视图:

mongodump --db test --collection testView --viewsAsCollections

这仅导出名为“ collection” (实际上是一个View)。 --viewsAsCollections意味着,除了返回mongodump而不是返回视图定义(本质上是聚合管道)之外,它还返回结果,就像返回一个真实的集合一样。

然后可以通过mongorestore加载生成的BSON内容:

mongorestore --db other --collection test

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

use other
db.test.find()

{ "_id" : ObjectId("5bfb3e0eadd1d8af906ad140"), "a" : 1, "b" : 2 }

还请注意,作为View,聚合管道实际上可以是任何东西,因此$match语句可以进行过滤,您可以随意转换甚至“聚合”。

将视图或--fieldsmongoexport一起使用

mongoexport实用程序大致相同,它也可以从视图中访问内容。

尽管这不是“严格BSON” ,但实际上MongoDB有一个标准,它实际上保留数据类型。实际上,MongoDB extended JSON下的文档中对此进行了介绍。

所以这不是二进制格式,并且作为JSON,它确实占用了更多的存储空间,但确实存在必要的信息。

例如:

db.mixed.insert({
  "a": NumberLong(1),
  "b": NumberDecimal("123.45"),
  "c": new Date(),
  "d":  "unwanted"
})

mongo外壳中显示为:

{
        "_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"
        }
}

或者与原始集合中的内容相同,只需使用--fields进行选择:

mongoexport --db test --collection mixed --fields a,b,c > out.json

具有完全相同的输出。唯一的限制是--query只能支持find()或类似的常规查询表达式。它不像View那样灵活,但是可以满足大多数需求的基本过滤。

Extended JSON可以被mongoimport识别,并且还有许多语言都可以使用的解析器实现,这些解析器也可以识别这种格式,并且在读取内容时,它会与保留“类型” 信息:

mongoimport --db other --collection mixed out.json

然后查看数据:

use other
db.mixed.findOne()
{
        "_id" : ObjectId("5bfb428790b2b4e4241a015c"),
        "a" : NumberLong(1),
        "b" : NumberDecimal("123.45"),
        "c" : ISODate("2018-11-26T00:47:03.033Z")
}

因此,在发送 binary 内容可能不可行甚至不希望发送但保持的情况下,有可能存在Extended JSON格式以用于数据交换。类型” 信息是可取的


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

作为“模糊” 段落的注释,在文档的Extended JSON页中列出了实际支持的BSON类型。您甚至可以将其与BSON Specification进行比较,以了解尽管有“谨慎” 语句,但实际上确实支持您将要使用的 common 类型的数据。尽管对该规范的一些外部解释可能并不坚持理解它们的 ALL ,但捆绑的实用程序(例如mongoexportmongoimport确实是合规的。