MongoDB(php)-将文档属性作为数组而不是多个属性返回

x33g5p2x  于 2023-11-17  发布在  Go
关注(0)|答案(6)|浏览(315)

我正在从mongodb数据库中阅读一个文档,并用php将其传递到客户端。
这个文档包含一个数组属性,问题是客户端接收到的是一个对象,它的属性名为01等等,而不是一个标准的数组。
这是原始数据:

  1. {
  2. "_id" : ObjectId("573b47a1f99a8a1f9a6278a5"),
  3. "persons" : [
  4. {
  5. "name" : "Moshe",
  6. },
  7. {
  8. "name" : "E",
  9. }, ...
  10. ]
  11. }

字符串
根据要求,我附上var_export:

  1. array (
  2. 0 =>
  3. MongoDB\Model\BSONDocument::__set_state(array(
  4. '_id' =>
  5. MongoDB\BSON\ObjectID::__set_state(array(
  6. )),
  7. 'persons' =>
  8. MongoDB\Model\BSONArray::__set_state(array(
  9. 0 =>
  10. MongoDB\Model\BSONDocument::__set_state(array(
  11. 'name' => 'Moshe',
  12. )),
  13. 1 =>
  14. MongoDB\Model\BSONDocument::__set_state(array(
  15. 'name' => 'E',
  16. )),
  17. )),
  18. )),
  19. )


var_dump:

  1. array(1) {
  2. [0]=>
  3. object(MongoDB\Model\BSONDocument)#40 (1) {
  4. ["storage":"ArrayObject":private]=>
  5. array(2) {
  6. ["_id"]=>
  7. object(MongoDB\BSON\ObjectID)#11 (1) {
  8. ["oid"]=>
  9. string(24) "573b47a1f99a8d1f986278a5"
  10. }
  11. ["persons"]=>
  12. object(MongoDB\Model\BSONArray)#34 (1) {
  13. ["storage":"ArrayObject":private]=>
  14. array(2) {
  15. [0]=>
  16. object(MongoDB\Model\BSONDocument)#10 (1) {
  17. ["storage":"ArrayObject":private]=>
  18. array(1) {
  19. ["name"]=>
  20. string(5) "Moshe"
  21. }
  22. }
  23. [1]=>
  24. object(MongoDB\Model\BSONDocument)#12 (1) {
  25. ["storage":"ArrayObject":private]=>
  26. array(1) {
  27. ["name"]=>
  28. string(1) "E"
  29. }
  30. }
  31. }
  32. }
  33. }
  34. }
  35. }


以下是PHP代码(全部):

  1. function select(){
  2. $conn = new MongoDB\Client("mongodb://localhost:27017");
  3. $db = $conn->mydb;
  4. $cursor = $db->entries_meta_data->find();
  5. return current($cursor->toArray());
  6. }


然后我用json_encode将对象传递给客户端,如下所示:

  1. echo json_encode(select());


在客户端显示的结果是:

  1. {
  2. "_id" : ObjectId("573b47a1f99a8a1f9a6278a5"),
  3. "persons" : {
  4. "0" : {
  5. "name" : "Moshe",
  6. },
  7. "1" : {
  8. "name" : "E",
  9. }, ...
  10. }
  11. }

**编辑:**LordNeo实际上解决了这个问题。在阅读他的答案后,我将“选择”函数中的最后一行改为:

  1. return json_decode(json_encode(current($cursor->toArray()),true);


它看起来很可怕,但它工作。
我很乐意听到更好的解决方案。

pwuypxnk

pwuypxnk1#

原因是new MongoDB driver处理MongoDB文档到PHP类型的转换不同于the old driver
好消息是,你可以通过指定一个所谓的“类型Map”来获得旧的行为。
文档有点隐藏,但你可以在in the github repository of the driver或在线文档中阅读。
TL;DR是你传递一个数组,

  1. array(
  2. 'array' => 'array',
  3. 'document' => 'array',
  4. 'root' => 'array'
  5. )

字符串
作为MongoDB\Client的构造函数的第三个参数(“driverOptions”),或者为每个查询单独调用MongoDB\Driver\Cursor::setTypeMap()
在您的示例中,调用

  1. $cursor->setTypeMap(array(
  2. 'array' => 'array',
  3. 'document' => 'array',
  4. 'root' => 'array'
  5. ));


$db->entries_meta_data->find()之后应该可以。

展开查看全部
6yoyoihd

6yoyoihd2#

MongoDB驱动程序提供了一个MongoDB\BSON\toJSON()函数,它可以正确地将数据转换为JSON。因为它需要一个字符串作为输入,所以你首先需要在文档上调用MongoDB\BSON\fromPHP()。因为看起来你只是想获取第一个找到的元素,所以你可以使用findOne()方法而不是find(),这使得获取输出非常容易:

  1. function select() {
  2. $conn = new MongoDB\Client("mongodb://localhost:27017");
  3. $db = $conn->mydb;
  4. $doc = $db->entries_meta_data->findOne();
  5. return MongoDB\BSON\toJSON(MongoDB\BSON\fromPHP($doc));
  6. }

字符串
如果你想输出多个条目,它会变得有点复杂。一种(公认的黑客)输出数组的方法如下所示:

  1. function select() {
  2. $conn = new MongoDB\Client("mongodb://localhost:27017");
  3. $db = $conn->mydb;
  4. $cursor = $db->entries_meta_data->find();
  5. $result = $cursor->toArray();
  6. foreach($result as $i => $doc) {
  7. $result[$i] = MongoDB\BSON\toJSON(MongoDB\BSON\fromPHP($doc));
  8. }
  9. return '[' . implode($res) . ']';
  10. }


另一种方法是调整json_encode()调用BSONArray类时的输出。为此,您需要调整setting up the MongoDB driver位于'vendor/mongodb/mongodb/src/Model'文件夹中时获得的BSONArray.php文件,并添加JsonSerializable接口和jsonSerialize()方法,使其看起来像这样:

  1. <?php
  2. ...
  3. class BSONArray extends ArrayObject implements \JsonSerializable,
  4. Serializable, Unserializable
  5. {
  6. ...
  7. /**
  8. * Serialize the ArrayObject as normal array
  9. *
  10. * @return array
  11. */
  12. public function jsonSerialize() {
  13. return $this->getArrayCopy();
  14. }
  15. }

展开查看全部
xlpyo6sf

xlpyo6sf3#

使用json_decode时,可以使用可选的“true”参数,它将关联到一个数组

  1. $obj = json_decode($json, true);
  2. //$obj will be an associative array

字符串
http://php.net/manual/en/function.json-decode.php
然后你可以使用array_shift剥离索引:

  1. $obj = array_shift($obj);


http://php.net/manual/en/function.array-shift.php
JSON在没有显式设置时添加数字索引,因此您可能应该向客户端发送一个数组,而不是再次解码->删除索引->编码->删除索引。
或者在客户端收到索引后删除索引。

ghg1uchk

ghg1uchk4#

是否有从0到n的所有索引或者它们中的任何一个缺失?这可能是原因。如果你想将它转换回数组,你可能会使用

  1. $obj = select(); // changed by the new line added

字符串
然后

  1. $obj['persons'] = array_values($obj['persons']);


去掉索引
我仍然很确定缺少了一些值,但是在你的例子中看不到。

hfwmuf9z

hfwmuf9z5#

mthierer几乎有正确的解决方案。
在示例化客户端时,您需要将typeMap放在驱动程序选项(第三个参数)中。
var driver_options ={'typeMap'=>{'root':'array ',' document':'array',' array':'array']}; var client = new MongoDB\Client(conn,options,driver_options);
这比在每次游标示例化之后都这样做要好。

bvn4nwqk

bvn4nwqk6#

对于任何需要使用Laravel雄辩和聚合的人,您可以将第二个参数$option传递给聚合方法

  1. Collection::raw(function ($collection) {
  2. $aggregationPipeLine = [];
  3. return $collection->aggregate($aggregationPipeLine, [
  4. 'typeMap' => [
  5. 'array' => 'array',
  6. 'document' => 'array',
  7. 'root' => 'array'
  8. ]
  9. ]);
  10. });

字符串
查看https://www.mongodb.com/docs/php-library/current/reference/method/MongoDBCollection-aggregate/#definition

相关问题