簡體   English   中英

MongoDB(php) - 將文檔屬性作為數組而不是多個屬性返回

[英]MongoDB (php) - return document property as an array instead of multiple properties

我正在從mongodb數據庫中讀取文檔並將其與php一起傳遞給客戶端。

該文檔包含一個數組屬性。 的問題是,在客戶端接收它作為一個對象與所述名稱屬性01等,而不是一個標准陣列。

這是原始數據:

{ 
    "_id" : ObjectId("573b47a1f99a8a1f9a6278a5"), 
    "persons" : [
        {
            "name" : "Moshe",
        }, 
        {
            "name" : "E",
        }, ...
    ]
}

根據要求,我附加了var_export:

array (
  0 => 
  MongoDB\Model\BSONDocument::__set_state(array(
     '_id' => 
    MongoDB\BSON\ObjectID::__set_state(array(
    )),
     'persons' => 
    MongoDB\Model\BSONArray::__set_state(array(
       0 => 
      MongoDB\Model\BSONDocument::__set_state(array(
         'name' => 'Moshe',
      )),
       1 => 
      MongoDB\Model\BSONDocument::__set_state(array(
         'name' => 'E',
      )),
    )),
  )),
)

和var_dump:

array(1) {
  [0]=>
  object(MongoDB\Model\BSONDocument)#40 (1) {
    ["storage":"ArrayObject":private]=>
    array(2) {
      ["_id"]=>
      object(MongoDB\BSON\ObjectID)#11 (1) {
        ["oid"]=>
        string(24) "573b47a1f99a8d1f986278a5"
      }
      ["persons"]=>
      object(MongoDB\Model\BSONArray)#34 (1) {
        ["storage":"ArrayObject":private]=>
        array(2) {
          [0]=>
          object(MongoDB\Model\BSONDocument)#10 (1) {
            ["storage":"ArrayObject":private]=>
            array(1) {
              ["name"]=>
              string(5) "Moshe"
            }
          }
          [1]=>
          object(MongoDB\Model\BSONDocument)#12 (1) {
            ["storage":"ArrayObject":private]=>
            array(1) {
              ["name"]=>
              string(1) "E"
            }
          }
        }
      }
    }
  }
}

這是PHP代碼(全部):

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

然后我用這樣的json_encode將對象傳遞給客戶端:

echo json_encode(select());

而在客戶端出現的結果是:

{ 
    "_id" : ObjectId("573b47a1f99a8a1f9a6278a5"), 
    "persons" : {
        "0" : {
            "name" : "Moshe",
        }, 
        "1" : {
            "name" : "E",
        }, ...
    }
}

編輯: LordNeo實際上解決了它。 在閱讀完答案后,我將“select”功能中的最后一行更改為以下內容:

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

它看起來很可怕,但它確實有效。

我將非常樂意聽到更好的解決方案。

原因是新的MongoDB驅動程序處理MongoDB文檔到不同於舊驅動程序的 PHP類型的轉換。

好消息是,您可以通過指定所謂的“類型映射”來獲取舊行為。

文檔有點隱藏,但您可以在驅動程序的github存儲庫在線文檔中閱讀它。

TL; DR就是你傳遞一個數組

array(
  'array' => 'array',
  'document' => 'array',
  'root' => 'array'
)

要么作為MongoDB \\ Client的構造函數的第3個參數(“driverOptions”), 要么為每個查詢單獨調用MongoDB \\ Driver \\ Cursor :: setTypeMap()

在您的示例中調用

$cursor->setTypeMap(array(
  'array' => 'array',
  'document' => 'array',
  'root' => 'array'
));

$db->entries_meta_data->find()應該做的伎倆。

MongoDB驅動程序提供MongoDB\\BSON\\toJSON()函數,該函數可正確地將數據轉換為JSON。 因為它需要一個字符串作為輸入,所以首先需要在文檔上調用MongoDB\\BSON\\fromPHP() 因為看起來你只想獲得第一個找到的元素,你可以使用findOne()方法而不是find() ,這樣可以很容易地得到輸出:

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

如果要輸出多個條目,則會更復雜一些。 輸出數組的一種(通常是hacky)方法如下所示:

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

另一種方法是在json_encode()調用時調整BSONArray類的輸出。 為此,您需要調整設置位於“vendor / mongodb / mongodb / src / Model”文件夾中的MongoDB驅動程序時獲得的BSONArray.php文件,並添加JsonSerializable接口和jsonSerialize()方法,以便它看起來像這樣:

<?php

...

class BSONArray extends ArrayObject implements \JsonSerializable,
    Serializable, Unserializable
{
    ...

    /**
     * Serialize the ArrayObject as normal array
     *
     * @return array
     */  
    public function jsonSerialize() {
        return $this->getArrayCopy();
    }
}

使用json_decode時,您可以使用可選的“true”參數,它將與數組關聯

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

http://php.net/manual/en/function.json-decode.php

然后你可以使用array_shift剝離索引:

$obj = array_shift($obj);

http://php.net/manual/en/function.array-shift.php

JSON在未明確設置時添加數字索引,因此您應該將數組發送到客戶端而不是解碼 - >刪除索引 - > enconding - >再次刪除索引。

或者只是在客戶端收到索引后刪除它。

是否存在從0到n的所有索引或者是否缺少任何索引? 這可能是原因。 如果要將其轉換回數組,可能會使用

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

接着

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

擺脫指數。

我仍然非常確定缺少一些價值。 但是從你的例子中看不出來。

mthierer幾乎有正確的解決方案。

在實例化客戶端時,需要將typeMap放在驅動程序選項(第3個參數)中。

var driver_options = {'typeMap'=> ['root':'array','document':'array','array':'array']}; var client = new MongoDB \\ Client(conn,options,driver_options);

這比在每次游標實例化后必須這樣做更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM