php Mongodb“$oid对存储无效“;从JSON导出插入时出错

php Mongodb“$oid对存储无效“;从JSON导出插入时出错,php,json,mongodb,Php,Json,Mongodb,我有一个文件,其中包含使用mongodb mongoexport命令导出的以下数据: mongoexport --db mydb --collection Users --out Users.json --jsonArray --journal Users.json包含: [ { "_id" : { "$oid" : "53c3e81ebb593fe827040ef7" }, "email" : "one@email.com", "password"

我有一个文件,其中包含使用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_转储:

(
  [_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进行测试。

默认情况下,使用MongoDB的标准。这是因为JSON在BSON所在的位置不是“类型化”的,某些数据应该是“类型化的”,在本例中是
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中的扩展表示“转换”这些特殊类型中的任何一种。

默认情况下,使用MongoDB的标准。这是因为JSON在BSON所在的位置不是“类型化”的,某些数据应该是“类型化的”,在本例中是
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的扩展表示中“转换”这些特殊类型。

Neil Lunn和Sammaye是正确的。他们给我指出了解决方案,并将Neils标记为正确

但我也想留下我自己的解决方案,因为你也可以有子文档,我结束了编写这个递归函数来替换所有的$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);
}  

Neil Lunn和Sammaye是正确的。他们给我指出了解决方案,并将Neils标记为正确

但我也想留下我自己的解决方案,因为你也可以有子文档,我结束了编写这个递归函数来替换所有的$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);
}  

您需要将序列化对象转换为其超级类型,即使用本例objectId/MongoId,您需要将序列化对象转换为其超级类型,即使用本例objectId/MongoId