MongoDB $ установлена ​​не обновляющая запись - PullRequest
12 голосов
/ 15 февраля 2012

Я экспериментирую с MongoDB с использованием расширения PHP PECL, однако у меня возникают трудности с выполнением определенного запроса на обновление.Я безуспешно искал ответы на SO.

Я создал базовую коллекцию:

$m = new Mongo;
$collection = $m->testdb->testcollection;

$collection->insert(array(
    0, 1, 1, 2, 3, 5
));

С использованием findOne и var_dump запись выглядит следующим образом:

array
  '_id' => 
    object(MongoId)[6]
      public '$id' => string '4f3bde65a1f7a0315b000000' (length=24)
  0 => int 0
  1 => int 1
  2 => int 1
  3 => int 2
  4 => int 3
  5 => int 5

Проблема возникает, когда я хочу обновить с помощью $set.Я основываю свой запрос на отображении в нижней части таблицы SQL для Монго в руководстве по PHP

Здесь я хочу обновить поле 0 до значения 100

$obj = $collection->findOne();

$collection->update(
    array('_id' => $obj['_id']),
    array('$set' => array(0 => 100))
);

Повторное извлечение записи показывает, что остается без изменений .

Мне было интересно, что я делаю что-то не так с _id, однако следующий запрос на обновление работает , хотя заменяет всю запись новым значением, а не просто обновляет его.field.

$collection->update(
    array('_id' => $obj['_id']),
    array(0 => 100)
);

Дамп объекта:

array
  '_id' => 
    object(MongoId)[7]
      public '$id' => string '4f3bde65a1f7a0315b000000' (length=24)
  0 => int 100

Может кто-нибудь указать, что я делаю неправильно, и как правильно использовать $set.Я уверен, что это очевидно, и мне просто нужна вторая пара глаз.

Большое спасибо.

Ответы [ 4 ]

11 голосов
/ 06 марта 2012

Я провел несколько расследований, почему это происходит. И я не думаю, что смогу найти способ, как «исправить» эту проблему.

JavaScript имеет различие между массивами и ассоциативными массивами / объектами. В PHP есть разница между массивами и объектами. Для PHP ассоциативный массив - это массив, а для JavaScript - это объект.

Когда драйверу PHP необходимо преобразовать массив в объект JSON, он пытается выяснить, является ли массив либо: обычным массивом с последовательно пронумерованными ключами, начинающимися с 0; или ассоциативный массив. Текущая реализация относится к любому массиву с последовательно пронумерованными ключами, начиная с 0 обычного массива. И обычный массив не содержит ключей . И это проблема. В ситуации, когда драйвер видит обычный массив, в BSON нет информации об имени поля, которая отправляется на сервер, и, следовательно, сервер не может обновить поле.

Я не могу придумать, как изменить это поведение, не нарушая существующий код. Поэтому, если вам нужны числовые имена полей, вы должны будете использовать объект stdClass для «основного документа». Кроме того, вы можете вставить эти ключи во встроенный документ и затем обновить:

<?php
$m = new Mongo;
$collection = $m->demo->testcollection;

$collection->insert(array(
    "_id" => 'bug341',
    'data' => array( 0, 1, 1, 2, 3, 5 )
));

$obj = $collection->findOne();

$update = array('data.0' => 'zero int');

$collection->update(
    array( '_id' => 'bug341' ),
    array( '$set' => $update )
);


$obj = $collection->findOne();
var_dump($obj);
?>
9 голосов
/ 16 февраля 2012

После выполнения различных тестов на основе комментария от yi_H и ответа от nnythm я обнаружил следующее.

Во всех случаях я использую этот общий код:

$collection->update(
    array('_id' => $obj['_id']),
    array('$set' => $updateObj)
);

Следующие не работают вообще:

  • $updateObj = array(0 => 100);
  • $updateObj = array('0' => 100);

Это работает:

  • $updateObj = array(1 => 100);
  • $updateObj = array('1' => 100);

Немного погуглив и прочитав некоторые документы по Mongo PHP, я обнаружил, что могу использовать объекты вместо массивов. Итак, я попробовал это:

$updateObj = new stdClass;
$updateObj->{0} = 100;

ЭТО РАБОТАЕТ!

Но я так и не смог выяснить, почему ...

Edit:

Просмотр исходного кода расширения Монго

Метод MongoCollection->update выполняет следующее: buf уже является указателем, а newobj является zval (второй параметр запроса). HASH_P просто возвращает правильное свойство zval для кодирования, в зависимости от того, массив это или объект.

zval_to_bson(buf, HASH_P(newobj), NO_PREP TSRMLS_CC)

Функция bson_encode выполняет следующее, идентичное с точки зрения функциональности. указатель буф и zval z.

zval_to_bson(&buf, HASH_P(z), 0 TSRMLS_CC);

Итак, я выполнил следующий тест.

$updateObj = new stdClass;
$updateObj->{0} = 100;

$one = bson_encode($updateObj);

$updateObj = array(0 => 100);

$two = bson_encode($updateObj);

var_dump($one === $two);

Выход true

Все еще в недоумении, почему 0 не работает для имени поля в массиве.

Редактировать 2:

Дальнейший эксперимент показывает, что когда в обновление включено поле с именем 0 (только для массива, объект в порядке) обновления не выполняются ни для каких полей

Пример:

$updateObj = array(
    '1' => 200
);

Работает, поле 1 обновлено.

$updateObj = array(
    '0' => 100,
    '1' => 200
);

Не работает , не , ни поле 0, ни 1 не обновляются.

Я думаю, что собираюсь отправить сообщение об ошибке.

0 голосов
/ 13 февраля 2016
we can update record in mongo db using php example below:-

$m = new MongoClient(<Put Replica set>); //PHP mongoclient function 
   echo "Connection to database successfully";
     $db = $m->dbname;  //put DB name
      $collection = $db->profile;

$document = array( 
                  "name" => $_REQUEST['name'], 
                  "email" => $_REQUEST['email'], 
                  "age" => $_REQUEST['age'],
                  "address" => $_REQUEST['address'],
                  "comment"=> $_REQUEST['comment']

               );

              // print_r($document); die;
             //echo $_REQUEST['pfid'];   
             $filter=array('_id'=>new MongoID( $_REQUEST['pfid'] ));
             $update=array('$set'=>$document);
    $collection->update( $filter, $update);
0 голосов
/ 16 февраля 2012

Вы не можете использовать число в качестве допустимого имени поля в mongodb. Попробуйте поместить поле «0» в кавычки, как оно реализовано в действительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...