Проблема с сохранением объектов в MongoDB

HraKK

Мудак
Команда форума
Нашел такую забавную особенность, если удалить из объекта все атриббуты то это станет не пустым объектом, а массивом. Внимание вопрос, этого можно как-то избежать?

И следом в догонку. Если я выбираю с указанием филда через дот нотацию, как выбрать определенный элемент массива? В объекте это легко "test.some.3".

Пример
"contract": {
"0": "lol",
"1": "lol2"
},
Удаляю "0", "1" получаю
"hero_contract": [

],

Спасибо!
 

johnbit

Новичок
Насколько мне известно, при сохранении всего объекта в целом от этого никак не избавится. Все из-за того, что и объекты и массивы, вытащенные из mongo, в php представляются массивами. И при сохранении в mongodb, драйвер mongo для php сохраняет массивами только пустые массивы и массивы с целочисленными ключами (начинающимися с 0 и без пропусков).

Решением может быть, например, использование update и указанием $unset для каждого атрибута - сам не пробовал, за результат не ручаюсь.
 

johnbit

Новичок
Попробовал:

Оказалось, что на самом деле объект остается объектом (это можно проверить через консоль mongo, а не каким-нибудь rockmongo), но в php он появится пустым массивом, что в принципе ОК (поэтому, кстати, он и будет отображен как пустой массив, например, в rockmongo). Но! Ошибка вылезет если вы потом целый объект сохраните, т.к. в этом случае этот пустой массив превратится в тот же пустой массив, а не пустой объект. Так что тут надо просто быть осторожным и стараться не хранить пустые объекты во избежание противоречий в их интерпретации.

Правило тут такое получается:
1) Оба: и пустой объект, и пустой массив загруженные из mongo, в php будут пустым массивом
2) Но: пустой массив php при сохранении всегда превратится в пустой массив в mongo, даже если изначально там был пустой объект.
 

johnbit

Новичок
По тому, что было "в догонку": не понятно зачем это нужно в реальности, но можно так, в два запроса:
db.test.update({},{'$unset':{'array.1':1}}); // элемент с индексом 1 будет выствлен в null
db.test.update({},{'$pull':{'array':null}}); // все элементы массива со значением null будут удалены
 

atv

Новичок
это всё из-за корявого json в ПХП, он работает по очень хитрому алгоритму
 

johnbit

Новичок
это всё из-за корявого json в ПХП, он работает по очень хитрому алгоритму
Так и есть, но ничего там хитрого нет. Я уже описал одно существенное замечание. Если кто знает еще какие подводные камни связанные с json в php - поделитесь, было бы интересно.
 

fixxxer

К.О.
Партнер клуба
Не уверен, что в тему, но может поможет сей факт

$ php -r 'var_dump(json_encode(array()));'
string(2) "[]"
$ php -r 'var_dump(json_encode(new StdClass));'
string(2) "{}"
 

johnbit

Новичок
Не уверен, что в тему, но может поможет сей факт

$ php -r 'var_dump(json_encode(array()));'
string(2) "[]"
$ php -r 'var_dump(json_encode(new StdClass));'
string(2) "{}"
Это верно, но проблема в данной теме вся в том, что в обратную сторону не работает. т.е. json_decode( "{}" ) должен вернуть пустой массив
 

johnbit

Новичок
Это верно, но проблема в данной теме вся в том, что в обратную сторону не работает. т.е. json_decode( "{}" ) должен вернуть пустой массив
Поправлю себя: json_decode сработает правильно. Так что проблема не в "кривом" json в php, а в том, что mongo всегда возвращает json объекты в виде ассоциированного массива, т.е. как будто бы он использует json_decode со вторым параметром true!
 

fixxxer

К.О.
Партнер клуба
mongo, или php extension? Во втором случае все поправимо
 

johnbit

Новичок
Вообщем, нарыл вот обсуждение с участием Кристины (разработчик драйвера mongo для php):

https://jira.mongodb.org/browse/PHP-16

В сухом остатке:
1) может помочь опция в php.ini: mongo.objects = 1
2) может не помочь, т.к. более года назад они откатили данную фичу. Что-то у них с этим были какие-то проблемы.

Вывод: мучаемся и учимся работать с массивами:)
 
Сверху