我有一个文件,其中包含使用mongodb mongoexport命令导出的以下数据:
mongoexport --db mydb --collection Users --out Users.json --jsonArray --journal
Users.json包含:
[
{
"_id" : { "$oid" : "53c3e81ebb593fe827040ef7" },
"email" : "one@email.com",
"password" : "$2y$10$OYN9qOPa8EAU202Nsee7s.jDyT8ntHq2mBkM4wWAMxDYvARRyKmr2"
}
]
我想在没有mongoimport命令的情况下导入数据,只使用php客户端,所以我做
$fixtures = file_get_contents($fixturesPath . '/' . $fixtureFile);
$rows = json_decode($fixtures, true);
foreach ($rows as $row) {
$this->db->Users->insert($row);
}
插入正确之前的$ row的var_dump:
(
[_id] => Array
(
[$oid] => 53c3e81ebb593fe827040ef7
)
[email] => one@email.com
[password] => $2y$10$OYN9qOPa8EAU202Nsee7s.jDyT8ntHq2mBkM4wWAMxDYvARRyKmr2
)
我收到以下错误:
[MongoWriteConcernException]
localhost:27017: $oid is not valid for storage.
问题是,如何从php导入这些数据呢? 显然通过删除_id行它可以工作,但我认为我需要这个id所以我可以使用用户ID进行测试。
答案 0 :(得分:3)
默认情况下,使用MongoDB的"extended JSON syntax"标准。这是因为在没有BSON的情况下JSON没有“打字”,并且某些数据应该被“打字”,在这种情况下是ObjectId
。
因此,如果您在“扩展语法”表单中处理JSON,则需要转换它:
foreach ( $rows as $row ) {
foreach ( array_keys($row) as $key) {
if ( $key == "_id" ) {
$row[$key] = new \MongoId( $row[$key]['$oid'] );
}
}
$this->db->Users->insert( $row );
}
或类似的东西,因为如果你“检测”这个和其他类型,循环在这里会更实用。但基本上你需要从JSON中的扩展表示中“转换”任何这些特殊类型。
答案 1 :(得分:2)
Neil Lunn和Sammaye是对的。他们向我指出了解决方案,并将尼尔斯标记为正确。
但是也想离开这里我自己的解决方案,因为你也可以有子文档我结束写这个递归函数来替换所有$ oid
private function replaceMongoIds(&$document, $name = false)
{
foreach (array_keys($document) as $key) {
if ($key == "_id" && isset($document[$key]['$oid'])) {
$document[$key] = new \MongoId($document[$key]['$oid']);
} else if ($name && is_array($document[$key]) && isset($document[$key]['$oid'])) {
$document[$key] = new \MongoId($document[$key]['$oid']);
} else if (is_array($document[$key]) ) {
$this->replaceMongoIds($document[$key], $key);
}
}
}
所以现在我的代码看起来像
$fixtures = file_get_contents($fixturesPath . '/' . $fixtureFile);
$rows = json_decode($fixtures, true);
foreach ($rows as $row) {
$this->replaceMongoIds($row);
$this->db->Users->insert($row);
}