mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-29 15:28:55 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@307768 c90b9560-bf6c-de11-be94-00142212c4b1
368 lines
9.5 KiB
XML
368 lines
9.5 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> gets its own slave, randomly
|
|
chosen from the readable slaves. This holds, even if you are using
|
|
persistent connections. So, if we do something like:
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// connects to a replica set with members ip0, ip1, and ip2
|
|
// ip0 is the primary, ip1 and ip2 are secondaries
|
|
$m1 = new Mongo("mongodb://ip0", array("replicaSet" => true, "persist" => "x"));
|
|
echo "m1's slave is ".$m1->getSlave()."\n";
|
|
|
|
// uses the same connection as $m1
|
|
$m2 = new Mongo("mongodb://ip0", array("replicaSet" => true, "persist" => "x"));
|
|
echo "m2's slave is ".$m2->getSlave()."\n";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<para>
|
|
we'd probably end up with something like:
|
|
</para>
|
|
<screen>
|
|
m1's slave is: ip2
|
|
m2's slave is: ip1
|
|
</screen>
|
|
|
|
<para>
|
|
If we continued to create new <classname>Mongo</classname>s, we should get a
|
|
fairly even distribution between ip1 and ip2. Keep in mind that all
|
|
secondaries listed by the <function>isMaster</function> command will be in
|
|
the pool of possible readers (even ones with priority 0 or slaveDelay set).
|
|
If you have certain servers you do not wish to read from, either route reads
|
|
manually or add the hidden option to the server's replica set configuration.
|
|
</para>
|
|
|
|
<para>
|
|
Slaves are chosen on a per-instance basis and do no change (unless something
|
|
bad happens to your set and they are forced to).
|
|
</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> (some fields omitted for
|
|
clarity):
|
|
</para>
|
|
<programlisting>
|
|
<![CDATA[
|
|
Array
|
|
(
|
|
[ubuntu:27017] => Array
|
|
(
|
|
[_id] => 0
|
|
[name] => ip0
|
|
[health] => 1
|
|
[state] => 1
|
|
[stateStr] => PRIMARY
|
|
)
|
|
|
|
[ubuntu:27019] => Array
|
|
(
|
|
[_id] => 2
|
|
[name] => ip1
|
|
[health] => 1
|
|
[state] => 2
|
|
[stateStr] => SECONDARY
|
|
)
|
|
|
|
[ubuntu:27018] => Array
|
|
(
|
|
[_id] => 1
|
|
[name] => ip2
|
|
[health] => 1
|
|
[state] => 2
|
|
[stateStr] => SECONDARY
|
|
)
|
|
|
|
)
|
|
]]>
|
|
</programlisting>
|
|
<para>
|
|
The set above has two readable servers, "ip1" and "ip2". If both of
|
|
these went down or became stale, reads would go to "ip0".
|
|
</para>
|
|
|
|
<para>
|
|
If you enjoy twiddling knobs that you probably shouldn't mess with, you can
|
|
force the driver to use a different slave by calling
|
|
<function>Mongo::switchSlave</function>. This randomly chooses a new slave
|
|
to use 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. You can manually force the
|
|
driver to update the status by calling <function>Mongo::getHosts</function>.
|
|
</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
|
|
-->
|
|
|