MongoCollection::insert

(PECL mongo >=0.9.0)

MongoCollection::insertInserta un documento en la colección

Descripción

public MongoCollection::insert ( array|object $document [, array $options = array() ] ) : bool|array

Todas los string que se envíen a la base de datos deben estar en UTF-8. Si un string no estuviera en UTF-8, se lanzará una MongoException. Para insertar (o consultar) un texto que no esté en UTF-8, utilice MongoBinData.

Parámetros

document

Un array u objeto. Si se utiliza un objeto, este no puede tener propiedades protegidas o privadas.

Nota:

Si el parámetro no posee una clave o propiedad _id, se creará una nueva instancia de MongoId y se le asignará. Este comportamiento especial no implica que el parámetro sea pasado por referencia.

options

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

  • "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 inserción si la opción "w" está establecida. De lo contrario, devuelve TRUE si el array insertado no está vacío (se lanzará una MongoException si el array insertado está vacío).

Si devuelve un array, las siguientes claves podrían estar presentes:

ok

Debería ser casi siempre 1 (a menos que last_error falle por sí mismo).

err

Si este campo es diferente de null, un error ocurrido en la operación anterior. Si este campo está establecido, será un string describiendo el error que ocurrió.

code

Si ocurrión un error de base de datos, el código de error relevante será devuelto al cliente.

errmsg

Este campo está establecido si algo va mal con un comando de base de datos. Está asociado con ok igual a 0. Por ejemplo, si se establece w y se agota el tiempo, errmsg será establecido a "timed out waiting for slaves" y ok será 0. Si este campo es establecido, será un string que describe el error ocurrido.

n

Si la última operación fue de inserción, una upsert, o una eliminación, será devuelto el número de objetos afectados. Para operaciones de inserción, este valor siempre es 0.

wtimeout

Si la opción anterior agota el tiempo, esperará a una réplica.

waited

Cuánto esperará la operación antes de agotarse el tiempo.

wtime

Si w fue establecido y la operación tiene éxito, cuánto toma la réplica a los servidores de w.

upserted

Si ocurre una upsert, este campo contendrá el nuevo campo _id del registro. Para upserts, estará presente este campo o updatedExisting (a menos que ocurra un error).

updatedExisting

Si una upsert actualiza un elemento existente, este campo será "true". Para upsert, estará presente este campo o 'upserted' (a menos que ocurra un error).

Errores/Excepciones

Lanza una MongoException si el documento insertado está vacío o si contiene claves de longitud cero. Intentar insertar un objeto con propiedades protegidas o privadas causará un error de clave de longitud cero.

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 booleano para indicar una escritura aceptada. En su lugar, ahora esto tiene que realizarse con array('w' => 1) (El comportamiento predeterminado de MongoClient).

1.2.0 Se añadió el parámetro "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.2 Cambiado el segundo parámetro a un array de opciones. Antes de la versión 1.0.2, el segundo parámetro era un booleano indicando la opción "safe".
1.0.1 Lanza una MongoCursorException si la opción "safe" está establecida y la inserción falla.

Ejemplos

Ejemplo #1 Ejemplo de MongoCollection::insert() con _id

Un campo _id será añadido al documento insertado si no estuviera ya presente. Dependiendo de cómo el parámetro sea pasado, estará disponible o no un _id generado para llamar al código.

<?php

$m 
= new MongoClient();
$colección $m->selectCollection('test''phpmanual');

// Si se usa un array literal, no hay forma de acceder al _id generado
$colección->insert(array('x' => 1));

// El _id está disponible en un array pasado por valor
$a = array('x' => 2);
$colección->insert($a);
var_dump($a);

// El _id no está disponible en un array pasado por referencia
$b = array('x' => 3);
$ref = &$b;
$colección->insert($ref);
var_dump($ref);

// El _id está disponible si una función envolvente no desencadena una copia durante la escritura
function insert_no_cow($colección$documento)
{
    
$colección->insert($documento);
}

$c = array('x' => 4);
insert_no_cow($colección$c);
var_dump($c);

// El _id no está disponible si una función envolvente desencadena una copia durante la escritura
function insert_cow($colección$documento)
{
    
$documento['y'] = 1;
    
$colección->insert($documento);
}

$d = array('x' => 5);
insert_cow($colección$d);
var_dump($d);

?>

El resultado del ejemplo sería algo similar a:

array(2) {
  ["x"]=>
  int(2)
  ["_id"]=>
  object(MongoId)#4 (0) {
  }
}
array(1) {
  ["x"]=>
  int(3)
}
array(2) {
  ["x"]=>
  int(4)
  ["_id"]=>
  object(MongoId)#5 (0) {
  }
}
array(1) {
  ["x"]=>
  int(5)
}

Ejemplo #2 Ejemplo de escritura aceptada con MongoCollection::insert()

Este ejemplo muestra cómo al insertar dos elementos con el mismo _id, se provoca que se lance una excepción MongoCursorException, ya que w está habilitado.

<?php

$persona 
= array("nombre" => "Joe""edad" => 20);
$colección->insert($persona);

// ahora $persona tiene un campo _id, así que si intentamos guardarlo
// de nuevo, obtendremos una excepción
try {
    
$collection->insert($persona, array("w" => 1));
} catch(
MongoCursorException $e) {
    echo 
"No se puede guardar dos veces la misma persona!\n";
}

?>

Ver también

add a note add a note

User Contributed Notes 6 notes

up
3
Christer Edvartsen
13 years ago
Also worth noting is that the MongoCollection::insert() method accepts objects as the first argument as well as arrays.

<?php
$data
= new stdClass;
$data->foo = 'foo';
$data->bar = 'bar';
$collection->insert($data);
var_dump($data->_id); // An instance of MongoId
?>

You can use other classes as well, but MongoCollection::insert() will fail if the object contains any protected or private properties. Public properties listed in the class will also be inserted:

<?php
class SomeClass {
    public
$foo = 'bar';
    public
$bar = 'foo';
}

$data = new SomeClass;
$data->foobar = 42;
$collection->insert($data);
var_dump($data->_id); // An instance of MongoId
?>

will result in a document with four elements:

_id => some mongoid
foo => 'bar'
bar => 'foo'
foobar => 42
up
2
gmail.com@mspreij
11 years ago
"Note: If the parameter does not have an _id key or property, a new MongoId instance will be created and assigned to it."

Note on note: this is true even if the insert *fails* (because of, say, duplicate key error). So even if no new document was inserted, the supplied array will still have a new MongoID key ->_id after the ->insert().

(which can make an attempted update after that fail, because you cannot update the _id value of a document..)
up
1
root at php dot net
11 years ago
_id and MongoId can be a source of problems that can make what would seem a trivial operation potentially complicated.

MongoId is not as predictable or safe as mysql's auto increment (an example that most PHP developers will be familiar with). _id is generated by the client rather than the server and so does not guarantee that it will be collision free.

By comparison, server side auto_increment mechanisms that PHP programmers might typically be used to wont collide until every single id had been used and with 64bits you can ensure this will almost never happen. You will also know when your table is getting full, and you can predict the rate. Most importantly, no matter the mechanism, being server side guarantees two clients wont collide. Mongo's behaviour is different to this.

Generally speaking inserting without specifying _id will tend to work, but there are some cases where is can fail or is particularly prone to failure.

The total size I believe is 96 bits. This might seem like a lot but the value is not created randomly. It is generated like this:

$unixtime . $machine_id . $pid . $counter

The counter starts from zero and is attached to each instance of MongoClient thus two MongoClient connections to the same server will almost certainly not work (produce a collision):

$m=new MongoWrapper();
$m->insert([0]);
$m=new MongoWrapper();
$m->insert([1]);

If MongoWrapper is not using a singleton for the connection or something to the same effect, the second call will most likely have the same unixtime. It will certainly have the same machine_id, pid and counter. The insert will fail.

If you are not using a singleton, this will work:

$m=new MongoWrapper();
$m->insert([0]);
$m->insert([1]);

You may also have difficulties in a multiple machine environment.

machine_id is a hash of gethostname. This is not guaranteed to be unique across machines. Some people do not set hostnames at all. If you do not ensure that your machines all have unique hostnames then if in the same second, two machines run a script that inserts, the second will have a 1 in 2^15 chance of colliding (assuming the most common PID max). Depending on how the system handles pids, the probability may actually be a little less. In short, make sure any host accessing your mongodb has a hostname that is unique among any other host accessing your mongodb.

I've seen some specs specify that counter should start from a random value but I highly recommend against this as it merely hides/obscures the problem.
up
1
mike at eastghost dot com
10 years ago
Attempting to insert() an array containing a NULL value followed by a blank space, in a non-utf8 encoding, results in the entire array (and all of its data) being ignored and the $opts array parameter being substituted instead as the data.
up
0
cuisdy at gmail dot com
12 years ago
Another rarity to keep in mind. Passing references has the same effect as passing a referenced object. Even if there's no different for PHP between those two, it's probably not evident. So, this code would not have the _id field added to $a:

<?php

$b
= &$a;

/* ... more code here ... */

$m = new MongoClient;
$collection = $m->test->phpmanual;

$a = array('x' => 12);

$collection->insert($a);
var_dump($a);
// array(1) { ["x"]=> int(12) }

?>

I've made the assignment above to show how this situation could happen, if you reassigned a var, for example. But it could be some normal referencing after giving $a its final value (but before calling insert), and the consequence would be the same: if a var is referenced, it won't get the _id appended.
up
0
John S.
12 years ago
Note, that the _id field will only be added to an inserted array if it does not already exist in the supplied array:

<?php
$data
= array('x' => 12);
var_dump($data);
$collection->insert($data);
var_dump($data);
?>

Will output something like:

array(1) {
  ["x"]=>
  int(12)
}
array(2) {
  ["x"]=>
  int(12)
  ["_id"]=>
  object(MongoId)#196 (1) {
    ["$id"]=>
    string(24) "503e21fc0605290912000000"
  }
}

however,

$data = array('x' => 12, '_id' => NULL);
var_dump($data);
$collection->insert($data);
var_dump($data);

will not have the same result:

array(2) {
  ["x"]=>
  int(12)
  ["_id"]=>
  NULL
}
array(2) {
  ["x"]=>
  int(12)
  ["_id"]=>
  NULL
}
To Top