Manuel
PHP Manual

Interrogation

Distribution des requêtes aux esclaves

Note: 1.1.0+

Si vous utilisez un » jeux de réplication ainsi que la version 1.1.0 ou suivante du driver, le driver peut automatiquement acheminer les lectures sur les esclaves. Ce comportement n'existe pas dans les précédentes versions du driver et ne peut pas être utilisé avec un serveur principal/esclave normal.

Par défaut, le driver envoie toutes les requêtes au serveur principal. Si vous définissez l'option "slaveOkay", le driver enverra toutes les requêtes à un serveur non-principal, si c'est possible. L'option "slaveOkay" peut être définie à plusieurs niveaux : à la connexion, à la base de données, à la collection, et au niveau du curseur. Chaque classe hérite de la configuration "slaveOkay" de la classe supérieure, aussi, si vous faites :

<?php

$db
->setSlaveOkay(true);
$c $db->myCollection;

$cursor $c->find();

?>

alors la requête sera exécutée sur un esclave (la collection hérite de "slaveOkay" depuis la base de données et le curseur en hérite de la collection).

Comment les esclaves sont choisis ?

Chaque instance de Mongo choisit son esclave en utilisant l'esclave ayant le ping le moins élevé. Ainsi, si nous avons un client PHP en Europe et un en Australie et que nous avons un esclave dans chacun de ces data-centers, nous pouvons faire :

<?php
// P est le primaire

// sur un client Australien
$m1 = new Mongo("mongodb://P", array("replicaSet" => true));
$m1->foo->bar->find()->slaveOkay()->getNext();
echo 
"L'esclave m1 est : ".$m1->getSlave()."\n";

// sur un client européen
$m2 = new Mongo("mongodb://P", array("replicaSet" => true));
$m2->foo->bar->find()->slaveOkay()->getNext();
echo 
"L'esclave m2 est : ".$m2->getSlave()."\n";

?>

nous pourrions constater quelque chose comme :


L'esclave m1 est : australianHost
L'esclave m2 est : europeanHost

Notez que nous devons exécuter une requête avant qu'un esclave ne soit choisi : les esclaves sont choisis par le driver. Mongo::getSlave() retournera FALSE tant qu'une esclave n'est pas utilisé.

Le driver connaît le statut courant de ces membres en exécutant la méthode Mongo::getHosts().

Si aucun serveur non-principal n'est disponible, le driver enverra la lecture vers le serveur principal (y compris si "slaveOkay" est défini). Un serveur est considéré comme accessible si son statut vaut 2 (SECONDARY) et sa santé, 1. Vous pouvez vérifier ces valeurs avec la méthode Mongo::getHosts() :

Si vous aimez toucher à ce que vous ne devriez pas, vous pouvez forcer le driver à utiliser un esclave différent en appelant la méthode Mongo::switchSlave(). Ceci choisira un nouvel esclave (s'il y en a un de disponible) et ne devrait pas être utilisé sauf si vous savez ce que vous faites.

Diverses notes

Les écritures sont toujours envoyées au serveur principal. Les commandes de base de données, y compris celles en lecture seule, sont également toujours envoyées au serveur principal.

La santé et le statut d'un esclave sont vérifiés toutes les 5 secondes ou bien lorsque la prochaine opération intervient après 5 secondes. La configuration est également re-vérifiée lorsque le driver a un problème pour atteindre un serveur.

Notez qu'un serveur non-principal peut être derrière le principal dans les opérations, ainsi, votre application doit admettre de recevoir des données non mises à jour (ou vous devez utiliser l'option w pour toutes les écritures).

Interrogation sur un _id

Chaque objet inséré se voit assigné automatiquement un champ unique _id, qui est bien utile pour être utilisé dans les requêtes.

Supposez que vous voulez trouver un document que vous venez tout juste d'insérer. L'insertion ajoute un champ _id au document, aussi, vous pouvez effectuer votre requête de la sorte :

<?php

$person 
= array("name" => "joe");

$people->insert($person);

// Maintenant, $joe a un champ _id
$joe $people->findOne(array("_id" => $person['_id']));

?>

Tant que l'utilisateur ne l'a pas spécifié autrement, le champ _id est un MongoId. L'erreur la plus courante est d'essayer d'utiliser une chaîne qui correspond à un MongoId. Gardez à l'esprit que cet identifiant a 2 types de données différents, et ne correspond pas l'un l'autre, de la même façon que la chaîne "array()" n'est pas la même chose qu'un tableau vide. Par exemple :

<?php

$person 
= array("name" => "joe");

$people->insert($person);

// Conversion de l'_id en une chaîne
$pid $person['_id'] . "";

// ECHEC - $pid est une chaîne, et non un MongoId
$joe $people->findOne(array("_id" => $pid));

?>

Les tableaux

Les tableaux sont spéciaux à plus d'un titre. Tout d'abord, il y a 2 types utilisés par MongoDB : des tableaux "normaux" et des tableaux associatifs. Les tableaux associatifs peuvent avoir plusieurs types de clés et de valeurs. Les tableaux "normaux" sont définis comme tableaux dans ces indices numériques ascendants, en commençant par 0 et s'incrémentant de 1 pour chaque élément. Ces 2 types correspondent à ce que vous connaissez déjà comme type en PHP.

Actuellement, si vous voulez sauvegarder la liste des récompenses dans un document, vous pouvez :

<?php

$collection
->save(array("awards" => array("gold""silver""bronze")));

?>

Les requêtes peuvent effectuer des recherches directement dans les éléments. Supposez que nous souhaitons trouver tous les documents dont l'élément du tableau est à une valeur fournie. Par exemple, les documents dont la récompense est l'or, comme ceci :

{ "_id" : ObjectId("4b06c282edb87a281e09dad9"), "awards" : ["gold", "silver", "bronze"]}

Ceci peut être effectué avec une requête simple, en ignorant le fait que "awards" est un tableau :

<?php

$cursor 
$collection->find(array("awards" => "gold"));

?>

Supposez que vous interrogiez la base de données avec un objet plus complexe, dont chaque élément du tableau sont eux-mêmes des objets, comme ceci :

{ 
     "_id" : ObjectId("4b06c282edb87a281e09dad9"), 
     "awards" : 
     [
        {
            "first place" : "gold"
        },
        {
            "second place" : "silver" 
        },
        {
            "third place" :  "bronze"
        }
     ]
}

Continuons d'ignorer que c'est un tableau. Nous pouvons utiliser la notation basée sur les points pour interroger le sous-objet :

<?php

$cursor 
$collection->find(array("awards.first place" => "gold"));

?>

Notez qu'il importe peu qu'il y ait un espace dans le nom du champ (bien qu'il convient de ne pas en mettre, juste pour rendre le code plus lisible).

Vous pouvez également utiliser un tableau contenant plusieurs valeurs à chercher. Actuellement, si nous cherchons les documents "gold" et "copper", nous pouvons le faire comme ceci :

<?php

$cursor 
$collection->find(array("awards" => array('$in' => array("gold""copper"))));

?>

Manuel
PHP Manual