MongoCollection::update

(PECL mongo >=0.9.0)

MongoCollection::updateActualizar registros basándose en los criterios proporcionados

Descripción

public MongoCollection::update ( array $criteria , array $new_object [, array $options = array() ] ) : bool|array

Parámetros

criteria

Criterios de consulta para los documentos a actualizar.

new_object

El objeto usado para actualizar los documentos coincidentes. Podría contener operadores de actualización (para modificar campos específicos) o ser un documento de remplazo.

options

Un array de opciones para la operación de actualización. Las opciones disponibles actualmente son:

  • "upsert"

    Si ningún documento cumple las condiciones de $criteria, se insertará un nuevo documento.

    Si se insertara un nuevo documento y $new_object contiene modificadores atómicos (esto es, operadores $), esas operaciones serán aplicadas al parámetro $criteria para crear el nuevo documento. Si $new_object no contiene modificadores atómicos, será utilizado tal cual para el documento insterdo. Véase los ejemplos de upsert abajo para más información.

  • "multiple"

    Todos los documentos que cumplan las condiciones de $criteria se actualizarán. MongoCollection::update() tiene exactamente el comportamiento contrario que MongoCollection::remove(): de forma predeterminada, actualiza sólo un documento, no todos los que cumplan las condiciones. Se recomienda especificar siempre se si deben actualizar múltiples documentos o un único documento, ya que el comportamiento predeterminado de la base de datos podría cambiar en el futuro.

  • "fsync"

    Booleano, cuyo valor predeterminado es FALSE. Si el registro en el diario está habilitado, funciona exactamente igual que "j". Si no está habilidato, la operación de escriturá bloqueará hasta que se sincronice con los ficheros de la base de datos del disco. Si es TRUE, implica una inserción reconocida y sobrescribirá el ajuste "w" a 0.

    Nota: Si está habilitada, se recomienda a los usuarios usar la opción "j" en lugar de "fsync". No use "fsync" y "j" simultáneamente, ya que resultará en un error.

  • "j"

    Booleano, cuyo valor predeterminado es FALSE. Fuerza a la operación de escritura a bloquear hasta que sea sincronizada con el diario del disco. Si es TRUE, implica una escritura reconocida y sobrescribirá el ajuste "w" a 0.

    Nota: Si se usa esta opción y el registro en el diario está deshabilitado, MongoDB 2.6+ emitirá un error y la escritura fallará; las versiones más antiguas del servidor simplemente ignoran esta opción.

  • "socketTimeoutMS"

    Esta opción especifica el tiempo límite, en milisegundos, para las comunicaciones con socket. Si el servidor no responde en el periodo especificado, se lanzará una MongoCursorTimeoutException y no habrá forma de determinar si el servidor manejó realmente la escritura o no. Se podría especificar un valor de -1 para bloquear indefinidamente. El valor predeterminado para MongoClient es 30000 (30 segundos).

  • "w"

    Véase WriteConcerns. El valor predeterminado de MongoClient es 1.

  • "wTimeoutMS"

    Esta opción especifica el tiempo límite, en milisegundos, para el reconocimiento de un asunto de escritura. Solamente es aplicable cuando "w" sea mayor que 1, ya que el tiempo de espera está relacionado con la replecación. Si el asunto de escritura no se satisface dentro del tiempo límite, se lanzará una MongoCursorException. Se puede especificar un valor de 0 para bloquear indefinidamente. El valor predeterminado es 10000 (diez segundos).

Las siguientes opciones están obsoletas y no deberían usarse más:

  • "safe"

    Obsoleto. Use la opción w de los asuntos de escritura.

  • "timeout"

    Alias obsoleto de "socketTimeoutMS".

  • "wtimeout"

    Alias obsoleto de "wTimeoutMS".

Valores devueltos

Devuelve un array que contiene el estado de la actualización si la opción "w" está establecida. De lo contrario, devuelve TRUE.

Los campos del array de estado están descritos en la documentación para MongoCollection::insert().

Errores/Excepciones

Lanza una MongoCursorException si la opción "w" está establecida y la escritura falla.

Lanza una MongoCursorTimeoutException si la opción "w" está establecida a un valor mayor que uno y la operación toma más de MongoCursor::$timeout milisegundos en completarse. Esto no pondrá fin a la operación en el servidor, es un tiempo límite del lado del cliente. La operación en MongoCollection::$wtimeout es milisegundos.

Historial de cambios

Versión Descripción
1.5.0

se añadió la opción "wTimeoutMS", la cual remplaza a "wtimeout". Emite un error de nivel E_DEPRECATED cuando se usa "wtimeout".

Se añadió la opción "socketTimeoutMS", la cual remplza a "timeout". Emite un error de nivel E_DEPRECATED cuando se usa "timeout".

Emite un error de nivel E_DEPRECATED al usar "safe".

1.3.4 Se añadió la opción "wtimeout".
1.3.0

Se añadió la opción "w".

El parámetro options ya no acepta un valor booleano para indicar un 'upsert'. En su lugar, esto ahora se tiene que hacer con array('upsert' => true).

1.2.11 Emite E_DEPRECATED cuando options es de tipo scalar.
1.2.0 Se añadió la opción "timeout".
1.0.11 Se desconecta en errores "not master" si "safe" está establecido.
1.0.9

Añadida la capacidad de pasar enteros a la opción "safe", la cual anteriormente únicamente aceptaba booleanos.

Añadida la opción "fsync".

Cambiado el tipo devuelto por un array que contiene información si se utiliza la opción "safe". De otro modo, se devuelve un booleano como antes.

1.0.5 Se añadió la opción "safe".
1.0.1 Cambiado el parámetro "opciones" de un booleano a un array. Antes de la versión 1.0.1, el segundo parámetro era valor booleano opcional especificando un upsert.

Ejemplos

Ejemplo #1 MongoCollection::update()

Añadiendo el campo dirección a un documento

<?php

$c
->insert(array("nombre" => "Pedro""apellido" => "Ruiz" ));
$nuevosdatos = array('$set' => array("direccion" => "Calle Juan, 1"));
$c->update(array("nombre" => "Pedro"), $nuevosdatos);

var_dump($c->findOne(array("nombre" => "Pedro")));

?>

El resultado del ejemplo sería algo similar a:

array(4) {
  ["_id"]=>
  object(MongoId)#6 (0) {
  }
  ["nombre"]=>
  string(3) "Pedro"
  ["apellido"]=>
  string(5) "Ruiz"
  ["direccion"]=>
  string(12) "Calle Juan, 1"
}

Ejemplo #2 Ejemplos de MongoCollection::update() con upsert

Los upserts pueden simplificar el código, ya que con una única línea se puede crear el documento si no existe (basado en $criteria), o actualizar un documento existente si coincide.

En el siguiente ejemplo, $new_object contiene un modificador atómico. Ya que la colección está vacía y upsert debe insertar un nuevo documento, aplicará esas operaciones al parámetro $criteria para crear el documento.

<?php

$c
->drop();
$c->update(
    array(
"uri" => "/summer_pics"),
    array(
'$inc' => array("page hits" => 1)),
    array(
"upsert" => true)
);
var_dump($c->findOne());
?>

El resultado del ejemplo sería algo similar a:

array(3) {
  ["_id"]=>
  object(MongoId)#9 (0) {
  }
  ["uri"]=>
  string(12) "/fotos_verano"
  ["accesos"]=>
  int(1)
}

Si $new_object no contiene modificadores atómicos (esto es, operadores $), upsert utilizará $new_object tal cual para el nuevo documento. Esto coincide con el comportamiento de una actualización normal, donde la no utilización de modificadores atómicos ocasiona la sobrescritura del documento.

<?php

$c
->drop();
$c->update(
    array(
"name" => "joe"),
    array(
"username" => "joe312""createdAt" => new MongoDate()), 
    array(
"upsert" => true)
);
var_dump($c->findOne());

?>

El resultado del ejemplo sería algo similar a:

array(3) {
  ["_id"]=>
  object(MongoId)#10 (0) {
  }
  ["usuario"]=>
  string(6) "juan312"
  ["fechaAlta"]=>
  object(MongoDate)#4 (0) {
  }
}

Ejemplo #3 Ejemplo de múltiples MongoCollection::update()

De forma predeterminada, MongoCollection::update() sólo actualizará el primer documento que encuentre que cumpla las condiciones de $criteria. Si fuera necesario, mediante la opción "multiple" podremos sobrescribir este comportamiento.

Este ejemplo añade un campo "regalo" a cada persona cuyo cumpleaños sea el próximo día.

<?php

$today 
= array('$gt' => new MongoDate(), '$lt' => new MongoDate(strtotime("+1 day")));
$people->update(
    array(
"birthday" => $today),
    array(
'$set' => array('gift' => $surprise)),
    array(
"multiple" => true)
);

?>
add a note add a note

User Contributed Notes 8 notes

up
18
nerds at limeworks dot com dot au
13 years ago
For anyone referencing records by the Mongo _id object, it's important to recognise that it is in fact an object, and not a string.

If you have a record with a Mongo ID of say "4e519d5118617e88f27ea8cd" that you are trying to retrieve or update, you cannot search for it using something like:
<?php
$m
= new Mongo();
$db = $m->selectDB('db');
$collection = 'collection';
$db->$collection->findOne(array('_id', '4e519d5118617e88f27ea8cd'));
?>

There is some documentation that mentions simple conversion to string will solve this, but I have found the only reliable way to locate records based on their ID is to first pass it to MondoID(), then use that for reference.

Something like this will be far more reliable:
<?php
$m
= new Mongo();
$db = $m->selectDB('db');
$collection = 'collection';
$mongoID = new MongoID('4e519d5118617e88f27ea8cd');
$db->$collection->findOne(array('_id', $mongoID));
?>

This may prove useful for anyone using the ID object like an auto-increment database key would be used in MySQL or similar.
up
13
joshuadburns at hotmail dot com
14 years ago
Please note under optional third parameter "options":

While the official MongoDB documentation references the keyword "multi" to flag the use of multiple updates, the PHP implementation uses the key "multiple" instead.

This may cause a little confusion if you're basing your keys on the OFFICIAL MongoDB documentation.
up
5
Vasiliy Makogon
11 years ago
if you want emulate on mongoDb "insert on duplicate key update" in SQL notation, you must use flag "upsert" with "$set" in "update" operation.

In this sample uses unique key (user id and product id) and date user visit  product:page. Each execute this code make update 'lasttime' field:

<?php
$client
= new \MongoClient(MONGO_DB);
$users = $client->users;
$last_views = $users->createCollection('last_views');
// create unique index
$result = $last_views->ensureIndex(
    array(
"user_id" => 1, "warecode" => 1),
    array(
"unique" => 1)
);

$uviews = new \stdClass();
$uviews->user_id = $this->user_id;
$uviews->warecode = $this->warecode;

$res = $users->last_views->update(
   
$uviews,
    array(
'$set' => array('lasttime' => new \MongoTimestamp())),
    array(
'upsert' => true)
);
?>
up
1
jeff at canuckistani dot ca
14 years ago
The return type of update changed in 1.09 if you are using safe => TRUE. It now returns something that looks like the info returned by MongoDB::lastError:

Array
(
    [err] =>
    [updatedExisting] => 1
    [n] => 1
    [ok] => 1
)
up
0
bronius at bcswebstudio dot com
10 years ago
Re. nerds @ limeworks comment:
Thanks for your helpful tip - right what I was looking for.  One note, though: Instead of comma, it's a => as in:
<?php
...->findOne(array('_id' => $mongoID);
?>
up
-3
rithish[at]gmail[dot]com
14 years ago
Do note, for incrementing a value using $inc, typecast the value to an integer before passing the new object to update().

<?php
$votes
= (int) $votes;
$newData = array('$inc' => array('votes'=>$votes));
$c->update(array("firstname" => "Bob"), $newData);
?>

This is especially noteworthy, if you are taking values from $_GET and pushing them for increment.
up
-3
bradzo0647 at gmail dot com
10 years ago
A need for an app was to add a new entry to the industries collection if it didn't already exist, and pass that "string" _id back to the caller to add it to the businesses collection (as a string also - database design by others.... :))

function GetIndustryID($db, $industry_name_eng, $industry_name_rus) {

// $db is the MongoDB database object
// $industry_name_eng is English of the industry name
// $industry_name_rus is Russian of the industry name

    if ( $industry_name_eng == "" && $industry_name_rus == "" ) {
        return "";
        exit;
    }
   
    // lookup russian version
    // of industry name from industries collection and try to return the _id
  
    // if not found, add this as a new document and return its _id

        // $c_ind = industry collection object
        // "industries" is the collection name

    $c_ind = $db->industries;

// you could use findOne here....
    $cursor = $c_ind->find(array('industry_name.russian' => $industry_name_rus));

    if ( $cursor->hasNext() ) {
        foreach ( $cursor as $document ) {         
            $id = $document['_id'];
        }
    } else {
        // not found here - go add it
        $document = array(
            "industry_id" => "",
            "industry_name" => array("english" => $industry_name_eng, "russian" => $industry_name_rus )
        );
        $db->industries->insert($document);
        $id = $document['_id'];   
       
        // update the industry_id in the industries collection
        // with the id returned - because we just added it, and
        // we need the industry_id the same as the _id
       
        // see: http://php.net/manual/en/mongocollection.update.php
       
        // update ( array $criteria , array $new_object [, array $options = array() ] )

                // note how I cast the MongoID "object" to a string
        $document['industry_id'] = (string)$id;
                // the $id in the next line is the ObjectID, not a string.
        $db->industries->update(array("_id" => $id), $document, array("upsert" => true));
    }
  
    return (string)$id;
              
}

Results: (using RoboMongo)
{
    "_id" : ObjectId("5427acf7a495dbd420b2e2ea"),
    "industry_id" : "5427acf7a495dbd420b2e2ea",
    "industry_name" : {
        "english" : "Oil and Gas",
        "russian" : "Нефть, Газ, Энергетика"
    }
}

It took me ages to work this out. Hope it helps someone else.
up
-5
Nanhe Kumar
8 years ago
$inc and set in one statement
<?php
    $m
= new Mongo();
   
$db = $m->selectDB('db');
   
$collection = 'collection';
   
$db->$collection->insert(array("firstname" => "Nanhe", "lastname" => "Kumar","attempt"=>1 ));
   
$newdata = array('$inc'=>array("attempt"=>1),'$set' => array("address" => "Delhi India"));
   
$db->$collection->update(array("firstname" => "Nanhe"), $newdata);
?>
To Top