2012-02-15 13 views
12

Eksperymentuję z MongoDB przy użyciu rozszerzenia PHP PECL, ale mam problem z uzyskaniem określonego zapytania aktualizacji. Szukałem na SO odpowiedzi na pytania przy odrobinie szczęścia.

Stworzyłem podstawową kolekcję:

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

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

Korzystanie findOne i var_dump zapis wygląda następująco:

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 

Problem pojawia się, gdy chcę zaktualizować przy użyciu $set. Ja opierając moje zapytanie na mapowaniu pokazanym kierunku dna SQL to Mongo Cheat Sheet w podręczniku PHP

Tutaj chcę zaktualizować pole 0 cenić 100

$obj = $collection->findOne(); 

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

Ponowne pobieranie rekord pokazuje, że szczątki niezmienione.

zrobiłem zastanawiać, czy robię coś źle z _id, jednak następującą kwerendę aktualizującą robi pracę, aczkolwiek zastępując cały rekord z nową wartość, a nie po prostu aktualizowanie jednego pola.

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

obiektu nora:

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

Czy ktoś mógłby wskazać co robię źle i jak prawidłowo używać $set. Jestem pewien, że to oczywiste i potrzebuję tylko drugiej pary oczu.

Wielkie dzięki.

+0

to działa: 'array ('$ zestaw' => array (1 => 100))'? –

+0

@yi_H: To ** działa **. Pole '1' jest zaktualizowane, dlaczego nie działa dla pola' 0'? – Leigh

Odpowiedz

11

Zrobiłem kilka badań, dlaczego tak się dzieje. I nie sądzę, żebym mógł znaleźć sposób na "naprawienie" tego problemu.

JavaScript ma różnicę między tablicami i asocjacyjnymi tablicami/obiektami. PHP ma różnicę między tablicami i obiektami. Dla PHP tablica asocjacyjna jest tablicą, a dla JavaScript jest obiektem.

Gdy sterownik PHP musi przekonwertować tablicę na obiekt JSON, próbuje ustalić, czy tablica to: normalna tablica z sekwencyjnie numerowanymi klawiszami zaczynającymi się od 0; lub tablica asocjacyjna. Bieżąca implementacja dotyczy dowolnej tablicy z sekwencyjnie numerowanymi kluczami, zaczynając od 0 normalnej tablicy. A normalna tablica nie zawiera kluczy . I to jest problem. W sytuacji, gdy sterownik widzi normalną tablicę, nie ma informacji o nazwie pola w BSON, który jest wysyłany do serwera, a zatem serwer nie może zaktualizować pola.

Nie mogę wymyślić sposób na zmianę tego zachowania bez łamania jakiegokolwiek istniejącego kodu. Więc jeśli chcesz mieć numeryczne nazwy pól, będziesz musiał użyć obiektu stdClass dla "dokumentu głównego". Alternatywnie można naciskać te klucze do osadzonego dokumentu, a następnie zaktualizować:

 
<?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

Nie można użyć liczby jako poprawnej nazwy pola w mongodb. Spróbuj umieścić swoje pole "0" w cudzysłowach, tak jak to jest zaimplementowane w rzeczywistości.

+0

'tablica ('$ set' => array ('0' => 100))' ma taki sam wynik, pole '0' nie jest aktualizowane. – Leigh

+2

Klucze tablic php to ciągi znaków ... –

9

Po wykonaniu różne testy, na podstawie uwag od yi_H i odpowiedzi z nnythm Znalazłem następujące.

We wszystkich przypadkach używam tego wspólnego kodu:

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

Poniższa nie działają w ogóle:

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

nich zrobić pracę:

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

Po trochę googlowania i czytając niektóre docs Mongo PHP, znalazłem mogę używać obiektów zamiast tablic. Tak więc spróbowałem:

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

TO DZIAŁA!

Ale nie byłem w stanie dowiedzieć się, dlaczego ...

Edit:

wywiercenie poprzez kodu źródłowego Mongo rozszerzenie

Sposób MongoCollection->update wykonuje następujące, buf jest już wskaźnik i newobj to zval (drugi parametr zapytania). HASH_P po prostu zwraca prawą właściwość zera dla kodowania, w zależności od tego, czy jest to tablica, czy obiekt.

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

Funkcja bson_encode wykonuje następujące, identycznego pod względem funkcjonalności. wskaźnik buf i zval z.

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

Przeprowadziłem następujący test.

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

$one = bson_encode($updateObj); 

$updateObj = array(0 => 100); 

$two = bson_encode($updateObj); 

var_dump($one === $two); 

Wyjście jest true

Mimo ze stratą dlaczego 0 nie działa na nazwę pola w tablicy.

Edit 2:

Kolejny eksperyment pokazuje, że gdy pole z nazwą 0 jest zawarte w aktualizacji (tylko tablica, obiekt jest w porządku) żadne aktualizacje są wykonywane na wszelkich polach

Przykład:

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

Works, pole 1 jest aktualizowana.

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

Czy nie pracy, ani pole 0 lub 1 są aktualizowane.

Myślę, że zamierzam przesłać raport o błędzie.

+0

z pewnością wygląda jak błąd - jeśli podasz sterownik PHP (https://jira.mongodb.org/browse/PHP) z tym rodzajem detalu, który masz powyżej, jestem pewien Kristina & Co. natychmiast znokautuje poprawkę :) –

+0

@AdamC: Argh, mają swój własny tracker problemów. Złożyłem już raport na pakiet PECL [w błędach PHP] (https://bugs.php.net/bug.php?id=61103), nienawidzę duplikowania tych rzeczy, ale ich własny system wydaje się być dużo bardziej aktywny . – Leigh

+0

Yep - wszyscy oficjalnie obsługiwani kierowcy mają swój własny tracker w Jira na stronie MongoDB.org. Jeśli nie dostaniesz trakcji na błędzie pakietu, po prostu otwórz tam i powiąż błąd pakietu. Aha, i biorąc pod uwagę szczegóły tutaj, nie jest to zły pomysł na link do tego pytania/odpowiedzi :) –

-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);