Consultas
Distribuyendo consultas a esclavos
Todas las consultas (lecturas y escrituras) solamente se envian al miembro primario de un
conjunto de réplicas de manera predeterminada. Sin embargo, esto es fácilmente configurable usando las
Preferencias de lectura, que permiten
establecer algunas preferencias de lectura genéricas (tales como permitir que un secundario lea
del servidor más cercano), y también proporcionar formas de dirigir específicamente un
servidor en un país concreto, o incluso hardware, usando los
conjuntos de etiquetas de conjuntos de réplicas.
Las preferencias de lectura se pueden configurar en cualquier nivel del controlador:
Cada clase hereda su configuración de preferencias de lectura del contexto "padre".
Ejemplo #1 Herencia de las preferencias de lectura del nivel de la base de datos hacia el cursor
<?php
$db->setReadPreference(MongoClient::RP_SECONDARY_PREFERRED);
$c = $db->myCollection;
$cursor = $c->find();
?>
En este ejemplo, la consulta se ejecutará en un secundario. La
colección hereda MongoClient::RP_SECONDARY_PREFERRED
de la base de datos y el cursor lo hereda de la colección.
Cómo se escogen los esclavos
Cada instancia de MongoClient escoge su propio
secundario utilizando el secundario disponible con el menor tiempo de respuesta. Es decir,
si tuviéramos un cliente PHP en Europa y otro en Australia y tuviéramos un secundario en
cada uno de estos centros de datos, podríamos hacer:
<?php
$options = array("replicaSet" => "setName", "readPreference" => MongoClient::RP_SECONDARY_PREFERRED);
// en el cliente de Australia
$m = new MongoClient("mongodb://primary,australianhost.secondary,europeanhost.secondary", $options);
$cursor = $m->foo->bar->find();
$cursor->getNext();
echo "Leyendo desde: ", $cursor->info()["server"], "\n";
// en el cliente de Europa
$m = new MongoClient("mongodb://primary,australianhost.secondary,europeanhost.secondary", $options);
$cursor = $m->foo->bar->find();
$cursor->getNext();
echo "Leyendo desde: ", $cursor->info()["server"], "\n";
?>
El resultado del ejemplo
sería algo similar a:
Reading from: australianHost
Reading from: europeanHost
Tenga en cuenta que se debe realizar una consulta antes de elegir un secundario:
los secundarios los elige el controlador de forma retardada, y para cada consulta por separado.
Se puede ver los que el controlador piensa que es el estado actual de los miembros
del conjunto ejecutando MongoClient::getHosts() o
MongoClient::getConnections().
Si un secundario no es legible, el controlador enviará las lecturas al
primario que se especificó con
MongoClient::RP_SECONDARY_PREFERRED
, que
recurrirá a ejecutar una consulta en un primario si no estuviera disponible un secundario.
Un servidor es considerado legible si su estado es 2 (SECONDARY) y su
salud es 1. Se puede verificar esto con
MongoClient::getHosts() y
MongoClient::getConnections().
Notas aleatorias
Las escrituras siempre se envian al primario y, de forma predeterminada, todas las lecturas
son enviada también al primario.
Consultando por _id
A cada objeto que se inserta se le asigna automáticamente un campo
_id único, el cual, a menudo, es un campo útil para usarlo en
consultas. Esto funciona de forma similar a la funcionalidad "obtener el último ID insertado",
excepto que el _id es escogido por el cliente.
Supongamos que queremos localizar el documento que acabamos de insertar. Las inserciones
añaden un campo _id al documento, de modo que podemos realizar una consulta a partir de él:
<?php
$person = array("name" => "joe");
$people->insert($person);
// ahora $joe tiene un campo _id
$joe = $people->findOne(array("_id" => $person['_id']));
?>
Salvo que se indique lo contrario, el campo _id será de tipo
MongoId. El error más frecuente consiste en usar una cadena
de texto que concuerde con un MongoId. Debe tenerse presente
que son dos tipos de datos distintos, y no concuerdan, del mismo modo que el texto
"array()" no es lo mismo que un array vacío. Por ejemplo:
<?php
$person = array("name" => "joe");
$people->insert($person);
// convertimos el _id a texto
$pid = $person['_id'] . "";
// FALLO - $pid es un texto, no un MongoId
$joe = $people->findOne(array("_id" => $pid));
?>
Arrays
Los arrays son especiales por varias razones. En primer lugar, hay dos tipos de arrays que
MongoDB utiliza: arrays "normales" y arrays asociativos. Los arrays asociativos pueden tener
cualquier combinación de claves y valores. Los arrays "normales" se definen como arrays
con un índice numérico ascendente que comienza por 0 y se incrementa en uno por cada
elemento. Estos son, normalmente, los arrays de PHP más comunes.
Por ejemplo, si se quisiera guardar una lista de premios en un documento, podríamos
poner:
<?php
$collection->save(array("awards" => array("gold", "silver", "bronze")));
?>
Las consultas pueden llegar hasta los arrays en busca de elementos. Supongamos que queremos
encontrar todos los documentos que contienen un elemento de un array con un determinado valor. Por ejemplo,
documentos con un premio "gold", como por ejemplo:
{ "_id" : ObjectId("4b06c282edb87a281e09dad9"), "awards" : ["gold", "silver", "bronze"]}
Esto puede lograrse con una única consulta, ignorando el hecho de que "awards" es
un array:
<?php
$cursor = $collection->find(array("awards" => "gold"));
?>
Supongamos que estamos consultando un objeto más complejo, si cada elemento del array
fuera un objeto en sí mismo, como en:
{
"_id" : ObjectId("4b06c282edb87a281e09dad9"),
"awards" :
[
{
"first place" : "gold"
},
{
"second place" : "silver"
},
{
"third place" : "bronze"
}
]
}
Incluso aquí, ignorando que se trata de un array, podemos usar la misma
notación para consultar al subobjeto:
<?php
$cursor = $collection->find(array("awards.first place" => "gold"));
?>
Debe tenerse en cuenta que no importa que haya espacios en los nombres de campos
(pese a que sea mejor no usarlos, sólo por mantenerlo más
legible).
Puede también usarse un array para consultar un determinado número de posibles valores. Por
ejemplo, si buscáramos documentos "gold" o "copper", podríamos hacer:
<?php
$cursor = $collection->find(array("awards" => array('$in' => array("gold", "copper"))));
?>