[英]How to return property of all elements of array inside MongoDB document?
[英]MongoDB (php) - return document property as an array instead of multiple properties
我正在從mongodb數據庫中讀取文檔並將其與php一起傳遞給客戶端。
該文檔包含一個數組屬性。 的問題是,在客戶端接收它作為一個對象與所述名稱屬性0
, 1
等,而不是一個標准陣列。
這是原始數據:
{
"_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.