2012-02-15 17 views
12

Sto sperimentando con MongoDB utilizzando l'estensione PECL PHP, tuttavia ho difficoltà a far funzionare una determinata query di aggiornamento. Ho cercato in giro su SO per le risposte con poca fortuna.

ho creato una collezione di base:

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

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

Utilizzando findOne e var_dump il record viene visualizzato come segue:

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 

Il problema nasce quando voglio aggiornare utilizzando $set. Sto basando la mia domanda sulla mappatura mostrato verso la parte inferiore del SQL to Mongo Cheat Sheet nel manuale PHP

Qui voglio aggiornare campo 0 a valorizzare 100

$obj = $collection->findOne(); 

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

Re-recupero il record dimostra che resti invariato.

mi sono chiesto se stavo facendo qualcosa di sbagliato con il _id, tuttavia la seguente query di aggiornamento fa lavoro, sia pure di sostituire l'intero record con un nuovo valore, non semplicemente aggiornando quello campo.

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

discarica Oggetto:

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

Qualcuno può sottolineare quello che sto facendo male, e come usare correttamente $set. Sono sicuro che sia ovvio e ho solo bisogno di un secondo paio di occhi su di esso.

Molte grazie.

+0

fa questo lavoro: 'array ('$ set' => array (1 => 100))'? –

+0

@yi_H: Questo ** funziona **. Il campo '1' è aggiornato, perché non funziona per il campo' 0'? – Leigh

risposta

11

Ho fatto alcune indagini sul perché questo accade. E non penso di poter trovare un modo su come "risolvere" questo problema.

JavaScript ha una differenza tra array e array/oggetti associativi. PHP ha la differenza tra array e oggetti. Per PHP un array associativo è un array e per JavaScript è un oggetto.

Quando il driver PHP deve convertire una matrice in un oggetto JSON, prova a capire se una matrice è: una matrice normale con chiavi numerate in sequenza che iniziano con 0; o un array associativo. L'implementazione corrente riguarda qualsiasi array con chiavi numerate in sequenza, a partire da 0 un array normale. E una matrice normale non contiene chiavi . E questo è il problema. Nella situazione il guidatore vede un array normale, non ci sono informazioni sul nome del campo nel BSON che viene inviato al server, e quindi il server non può aggiornare un campo.

Non riesco a pensare a un modo per modificare questo comportamento senza rompere alcun tipo di codice esistente. Quindi se vuoi nomi di campi numerici, dovrai usare un oggetto stdClass per il "documento principale". In alternativa, si potrebbe spingere quelle chiavi in ​​un documento incorporato e quindi aggiornare:

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

Non è possibile utilizzare un numero come nome di campo valido in mongodb. Prova a mettere il tuo campo "0" tra virgolette, che è il modo in cui è implementato in realtà.

+0

'array ('$ set' => array ('0' => 100))' ha lo stesso risultato, il campo '0' non viene aggiornato. – Leigh

+2

php array keys are string ... –

9

Dopo aver effettuato varie prove, in base al commento da yi_H e risposta da nnythm ho trovato quanto segue.

In tutti i casi Sto usando questo codice comune:

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

La seguente non funzionano affatto:

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

questi lavori:

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

Dopo un po 'di googling e leggere alcuni dei documenti Mongo PHP, ho trovato posso usare oggetti invece di array. Così ho provato questo:

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

QUESTO FUNZIONA!

Ma io non sono stato in grado di scoprire il perché ...

Edit:

Frugando attraverso il codice sorgente di mongo estensione

Il metodo MongoCollection->update esegue quanto segue, buf è già un puntatore e newobj è uno zval (il secondo parametro della query). HASH_P restituisce semplicemente la proprietà corretta dello zval per la codifica, a seconda che si tratti di un array o di un oggetto.

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

La funzione bson_encode esegue quanto segue, identica in termini di funzionalità. buf pointer e zval z.

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

Così ho eseguito il seguente test.

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

$one = bson_encode($updateObj); 

$updateObj = array(0 => 100); 

$two = bson_encode($updateObj); 

var_dump($one === $two); 

L'uscita è true

Ancora in perdita perché 0 non funziona per un nome di campo in un array.

Edit 2:

Un ulteriore esperimento dimostra che quando un campo con un nome di 0 è incluso nell'aggiornamento (solo array, oggetto va bene) aggiornamenti vengono eseguiti su tutti i campi

Esempio:

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

Works, campo 1 viene aggiornato.

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

Does non lavoro, né campo 0 o 1 vengono aggiornati.

Penso che ho intenzione di presentare un bug report.

+0

sembra sicuramente un bug - se si invia al driver PHP (https://jira.mongodb.org/browse/PHP) con il tipo di dettagli che hai sopra sono sicuro Kristina & Co. eliminerà una correzione in poco tempo :) –

+0

@AdamC: Argh, hanno il proprio tracker di problemi. Ho già inviato un rapporto per il pacchetto PECL [in bug PHP] (https://bugs.php.net/bug.php?id=61103), odio duplicare queste cose ma il loro sistema sembra essere molto più attivo . – Leigh

+0

Sì, tutti i driver ufficialmente supportati hanno il proprio tracker in Jira sul sito MongoDB.org. Se non si ottiene alcuna trazione sul bug del pacchetto, è sufficiente aprirne uno e fare riferimento al bug del pacchetto. Oh, e dato il dettaglio qui, non è una cattiva idea collegare a questa domanda/risposta :) –

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