php-doc-en/reference/mongo/queries.xml
Kristina Chodorow 895044720b fixed description of getSlave
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@313052 c90b9560-bf6c-de11-be94-00142212c4b1
2011-07-07 14:17:31 +00:00

325 lines
8.2 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<section xml:id="mongo.queries" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Querying</title>
<section>
<title>Distributing queries to slaves</title>
<note>
<title>1.1.0+</title>
<para>
If you are using a
<link xlink:href="&url.mongodb.replica;">replica set</link> and version
1.1.0 or above of the driver, the driver can automatically route reads to
slaves. This behavior does not exist in earlier versions of the driver and
<emphasis>cannot</emphasis> be used with "normal" master-slave.
</para>
</note>
<para>
By default, the driver will send all queries to the master. If you set the
"slaveOkay" option, the driver will send all queries to a non-primary server,
if possible. The "slaveOkay" option can be set at every "level":
<link linkend="mongo.setslaveokay">connection</link>,
<link linkend="mongodb.setslaveokay">database</link>,
<link linkend="mongocollection.setslaveokay">collection</link>, and
<link linkend="mongocursor.slaveokay">cursor</link>. Each class inherits the
"slaveOkay" setting from the class above it, so if you do:
</para>
<programlisting role="php">
<![CDATA[
<?php
$db->setSlaveOkay(true);
$c = $db->myCollection;
$cursor = $c->find();
?>
]]>
</programlisting>
<para>
then the query will be executed against a slave (the collection inherited
"slaveOkay" from the database and the cursor inherited it from the
collection).
</para>
<section>
<title>How slaves are chosen</title>
<para>
Each instance of <classname>Mongo</classname> chooses its own slave using
the available slave with the lowest ping time. So, if we had a PHP client
in Europe and one in Australia and we had one secondary in each of these
data centers, we could do:
</para>
<programlisting role="php">
<![CDATA[
<?php
// P is the primary
// on the Australian client
$m1 = new Mongo("mongodb://P", array("replicaSet" => true));
$m1->foo->bar->find()->slaveOkay()->getNext();
echo "m1's slave is ".$m1->getSlave()."\n";
// on the European client
$m2 = new Mongo("mongodb://P", array("replicaSet" => true));
$m2->foo->bar->find()->slaveOkay()->getNext();
echo "m2's slave is ".$m2->getSlave()."\n";
?>
]]>
</programlisting>
<para>
we'd probably end up with something like:
</para>
<screen>
m1's slave is: australianHost
m2's slave is: europeanHost
</screen>
<para>
Note that we have to do a query before a slave is chosen: slaves are chosen
lazily by the driver. <function>Mongo::getSlave</function> will return
&null; until a slave is used.
</para>
<para>
You can see what the driver thinks is the current status of the set members
by running <function>Mongo::getHosts</function>.
</para>
<para>
If no non-primary server is readable, the driver will send
reads to the primary (even if "slaveOkay" is set). A server is considered
readable if its state is 2 (SECONDARY) and its health is 1. You can check
this with <function>Mongo::getHosts</function>.
</para>
<para>
If you enjoy twiddling knobs that you probably shouldn't mess with, you can
request the driver to use a different slave by calling
<function>Mongo::switchSlave</function>. This may choose a new slave
(if one is available) and shouldn't be used unless you know what you're
doing.
</para>
</section>
<section>
<title>Random notes</title>
<para>
Writes are always sent to the primary. Database commands, even read-only
commands, are also always sent to the primary.
</para>
<para>
The health and state of a slave is checked every 5 seconds or when the next
operation occurs after 5 seconds. It will also recheck the configuration
when the driver has a problem reaching a server.
</para>
<para>
Note that a non-primary server may be behind the primary in operations, so
your application must be okay with getting out-of-date data (or you must use
w for all writes).
</para>
</section>
</section>
<section>
<title>Querying by _id</title>
<para>
Every object inserted is automatically assigned a unique _id field, which is
often a useful field to use in queries.
</para>
<para>
Suppose that we wish to find the document we just inserted. Inserting adds
and _id field to the document, so we can query by that:
<programlisting role="php">
<![CDATA[
<?php
$person = array("name" => "joe");
$people->insert($person);
// now $joe has an _id field
$joe = $people->findOne(array("_id" => $person['_id']));
?>
]]>
</programlisting>
</para>
<para>
Unless the user has specified otherwise, the _id field is a
<classname>MongoId</classname>. The most common mistake is attepting to use
a string to match a <classname>MongoId</classname>. Keep in mind that these
are two different datatypes, and will not match each other in the same way
that the string "array()" is not the same as an empty array. For example:
<programlisting role="php">
<![CDATA[
<?php
$person = array("name" => "joe");
$people->insert($person);
// convert the _id to a string
$pid = $person['_id'] . "";
// FAILS - $pid is a string, not a MongoId
$joe = $people->findOne(array("_id" => $pid));
?>
]]>
</programlisting>
</para>
</section>
<section>
<title>Arrays</title>
<para>
Arrays are special in a couple ways. First, there are two types that
MongoDB uses: "normal" arrays and associative arrays. Associative arrays can
have any mix of key types and values. "Normal" arrays are defined as arrays
with ascending numeric indexes starting at 0 and increasing by one for each
element. These are, typically, just your usual PHP array.
</para>
<para>
For instance, if you want to save a list of awards in a document, you could
say:
</para>
<programlisting role="php">
<![CDATA[
<?php
$collection->save(array("awards" => array("gold", "silver", "bronze")));
?>
]]>
</programlisting>
<para>
Queries can reach into arrays to search for elements. Suppose that we wish
to find all documents with an array element of a given value. For example,
documents with a "gold" award, such as:
</para>
<programlisting>
<![CDATA[
{ "_id" : ObjectId("4b06c282edb87a281e09dad9"), "awards" : ["gold", "silver", "bronze"]}
]]>
</programlisting>
<para>
This can be done with a simple query, ignoring the fact that "awards" is an
array:
</para>
<programlisting role="php">
<![CDATA[
<?php
$cursor = $collection->find(array("awards" => "gold"));
?>
]]>
</programlisting>
<para>
Suppose we are querying for a more complex object, if each element of the
array were an object itself, such as:
</para>
<programlisting>
<![CDATA[
{
"_id" : ObjectId("4b06c282edb87a281e09dad9"),
"awards" :
[
{
"first place" : "gold"
},
{
"second place" : "silver"
},
{
"third place" : "bronze"
}
]
}
]]>
</programlisting>
<para>
Still ignoring that this is an array, we can use dot notation to query the
subobject:
</para>
<programlisting role="php">
<![CDATA[
<?php
$cursor = $collection->find(array("awards.first place" => "gold"));
?>
]]>
</programlisting>
<para>
Notice that it doesn't matter that there is a space in the field name
(although it may be best not to use spaces, just to make things more
readable).
</para>
<para>
You can also use an array to query for a number of possible values. For
instance, if we were looking for documents "gold" or "copper", we could do:
</para>
<programlisting role="php">
<![CDATA[
<?php
$cursor = $collection->find(array("awards" => array('$in' => array("gold", "copper"))));
?>
]]>
</programlisting>
</section>
</section>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->