2012-02-15 4 views
12

Я экспериментирую с 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 to Mongo Cheat Sheet в PHP инструкции

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

$obj = $collection->findOne(); 

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

Re сгрузить запись показывает, что остатки без изменений.

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

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

Объект свалка:

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

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

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

+0

делает эту работу: 'массив ('$ набор' => массив (1 => 100))'? –

+0

@yi_H: Это ** делает ** произведение. Поле '1' обновляется, почему он не работает для поля' 0'? – Leigh

ответ

11

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

У 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); 
?> 
0

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

+0

'array ('$ set' => array ('0' => 100))' имеет тот же результат, поле '0' не обновляется. – Leigh

+2

ключи массива php являются строками ... –

9

После выполнения различных тестов, основанных на комментарий от 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);

После немного прибегая к помощи и читать некоторые документы Монго PHP, я нашел, что я могу использовать объекты вместо массивов. Поэтому я пробовал это:

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

ЭТО РАБОТЫ!

Но я не был в состоянии выяснить, почему ...

Edit:

Poking через Монго исходного кода расширения

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

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

Функция bson_encode выполняет следующие функции, идентичные по функциональным возможностям. buf указатель и 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

, конечно, выглядит как ошибка - если вы отправляете драйвер PHP (https://jira.mongodb.org/browse/PHP) с той деталью, которую вы имеете выше, я уверен Kristina & Co. будет выбивать исправление в кратчайшие сроки :) –

+0

@AdamC: Argh, у них есть свой собственный трекер. Я уже отправил отчет для пакета PECL [в PHP-ошибках] (https://bugs.php.net/bug.php?id=61103), я ненавижу дублировать эти вещи, но их собственная система, кажется, намного активнее , – Leigh

+0

Yep - все официально поддерживаемые драйверы имеют свой собственный трекер в Jira на сайте MongoDB.org. Если вы не получаете никакого сцепления с ошибкой пакета, просто откройте его и укажите ошибку пакета. О, и, учитывая подробности здесь, неплохая идея связать с этим вопросом/ответом :) –

-1
we can update record in mongo db using php example below:- 

$m = new MongoClient(); 
    echo "Connection to database successfully"; 
    $db = $m->unified; 
     $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);