mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00

Patch by carusogabriel. Closes php/doc-en#7. git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@347749 c90b9560-bf6c-de11-be94-00142212c4b1
382 lines
11 KiB
XML
382 lines
11 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<chapter xml:id="mongo.queries" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>Querying</title>
|
|
|
|
<simplesect xml:id="mongo.queries.secondaries">
|
|
<title>Distributing queries to secondaries</title>
|
|
|
|
<para>
|
|
All queries (reads and writes) are only sent to the primary member of a
|
|
replica set by default. This is however easily configurable by using the
|
|
<link linkend="mongo.readpreferences">Read Preferences</link> which allow
|
|
you to set some generic read preferences (such as allowing secondary reads
|
|
of the nearest server), and also provide ways to specifically target a
|
|
server in a specific country, datacenter, or even hardware, by the use of
|
|
<link linkend="mongo.readpreferences.tagsets">replica set tag sets</link>.
|
|
</para>
|
|
<para>
|
|
Read preferences can be configured at every level of the driver:
|
|
<simplelist>
|
|
<member>As a query parameter or option to <methodname>MongoClient::__construct</methodname></member>
|
|
<member>Specifically by calling <methodname>MongoClient::setReadPreference</methodname></member>
|
|
<member>At the database level with <methodname>MongoDB::setReadPreference</methodname></member>
|
|
<member>At the collection level with <methodname>MongoCollection::setReadPreference</methodname></member>
|
|
<member>At the cursor level with <methodname>MongoCursor::setReadPreference</methodname> or <methodname>MongoCommandCursor::setReadPreference</methodname></member>
|
|
</simplelist>
|
|
Each class inherits its read preference setting from the "parent" context.
|
|
</para>
|
|
<example xml:id="mongo.queries.secondaries.inheritence-example">
|
|
<title>Inheriting read preferences from the database level down to the cursor</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$db->setReadPreference(MongoClient::RP_SECONDARY_PREFERRED);
|
|
$c = $db->myCollection;
|
|
|
|
$cursor = $c->find();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
In this example, the query will be executed against a secondary. The
|
|
collection inherits <constant>MongoClient::RP_SECONDARY_PREFERRED</constant>
|
|
from the database and the cursor inherits it from the collection.
|
|
</para>
|
|
</simplesect>
|
|
|
|
<simplesect xml:id="mongo.queries.choosing.secondary">
|
|
<title>How secondaries are chosen</title>
|
|
|
|
<para>
|
|
Each instance of <classname>MongoClient</classname> chooses its own
|
|
secondary using the available secondary 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>
|
|
<example xml:id="mongo.queries.choosing.secondary-example">
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$options = array("replicaSet" => "setName", "readPreference" => MongoClient::RP_SECONDARY_PREFERRED);
|
|
|
|
// on the Australian client
|
|
$m = new MongoClient("mongodb://primary,australianhost.secondary,europeanhost.secondary", $options);
|
|
$cursor = $m->foo->bar->find();
|
|
$cursor->getNext();
|
|
echo "Reading from: ", $cursor->info()["server"], "\n";
|
|
|
|
// on the European client
|
|
$m = new MongoClient("mongodb://primary,australianhost.secondary,europeanhost.secondary", $options);
|
|
$cursor = $m->foo->bar->find();
|
|
$cursor->getNext();
|
|
echo "Reading from: ", $cursor->info()["server"], "\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Reading from: australianHost
|
|
Reading from: europeanHost
|
|
]]>
|
|
</screen>
|
|
<para>
|
|
Note that we have to do a query before a secondary is chosen: secondaries
|
|
are chosen lazily by the driver, and for each query separately.
|
|
</para>
|
|
</example>
|
|
|
|
<para>
|
|
You can see what the driver thinks is the current status of the set
|
|
members by running <methodname>MongoClient::getHosts</methodname> or
|
|
<methodname>MongoClient::getConnections</methodname>.
|
|
</para>
|
|
|
|
<para>
|
|
If no secondary is readable, the driver will send reads to the
|
|
primary as we specified
|
|
<constant>MongoClient::RP_SECONDARY_PREFERRED</constant> which will
|
|
fallback to execute a query on a primary if no secondaries are available.
|
|
A server is considered readable if its state is 2 (SECONDARY) and its
|
|
health is 1. You can check this with
|
|
<methodname>MongoClient::getHosts</methodname> and
|
|
<methodname>MongoClient::getConnections</methodname>.
|
|
</para>
|
|
|
|
</simplesect>
|
|
<simplesect xml:id="mongo.queries.notes">
|
|
<title>Random notes</title>
|
|
|
|
<para>
|
|
Writes are always sent to the primary—and by default all reads are sent
|
|
to the primary too.
|
|
</para>
|
|
<!--
|
|
<para>
|
|
The following database commands can be sent to secondaries when using the
|
|
apropriate Read Preference:
|
|
<simplelist>
|
|
<member><methodname>MongoCollection::group</methodname></member>
|
|
<member><methodname>MongoCollection::aggregate</methodname></member>
|
|
<member><methodname>MongoCollection::distinct</methodname></member>
|
|
<member><methodname>MongoCursor::count</methodname></member>
|
|
<member>collStats</member>
|
|
<member>dbStats</member>
|
|
<member>geoNear</member>
|
|
<member>geoSearch</member>
|
|
<member>geoWalk</member>
|
|
<member>inline mapreduce</member>
|
|
</simplelist>
|
|
All other commands are always sent to the primary.
|
|
</para>
|
|
-->
|
|
</simplesect>
|
|
|
|
<simplesect xml:id="mongo.queries.querying">
|
|
<title>Querying by _id</title>
|
|
<para>
|
|
Every object inserted is automatically assigned a unique
|
|
<literal>_id</literal> field, which is often a useful field to use in
|
|
queries. This works similarly to "get last insert ID" functionality, except
|
|
that the <literal>_id</literal> is chosen by the <emphasis>client</emphasis>.
|
|
</para>
|
|
<para>
|
|
Suppose that we wish to find the document we just inserted. Inserting adds
|
|
an <literal>_id</literal> field to the document, so we can query by that:
|
|
|
|
<example xml:id="mongo.queries.querying-example">
|
|
<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>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Unless the user has specified otherwise, the <literal>_id</literal> field is a
|
|
<classname>MongoId</classname>. The most common mistake is attempting 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:
|
|
|
|
<example xml:id="mongo.queries.querying.wrong">
|
|
<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>
|
|
</example>
|
|
</para>
|
|
</simplesect>
|
|
|
|
<simplesect xml:id="mongo.queries.arrays">
|
|
<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>
|
|
|
|
<example xml:id="mongo.queries.arrays-example">
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$collection->save(array("awards" => array("gold", "silver", "bronze")));
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<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>
|
|
|
|
<screen>
|
|
<![CDATA[
|
|
{ "_id" : ObjectId("4b06c282edb87a281e09dad9"), "awards" : ["gold", "silver", "bronze"]}
|
|
]]>
|
|
</screen>
|
|
|
|
<para>
|
|
This can be done with a simple query, ignoring the fact that "awards" is an
|
|
array:
|
|
</para>
|
|
|
|
<example xml:id="mongo.queries.arrays-example-2">
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$cursor = $collection->find(array("awards" => "gold"));
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Suppose we are querying for a more complex object, if each element of the
|
|
array were an object itself, such as:
|
|
</para>
|
|
|
|
<screen>
|
|
<![CDATA[
|
|
{
|
|
"_id" : ObjectId("4b06c282edb87a281e09dad9"),
|
|
"awards" :
|
|
[
|
|
{
|
|
"first place" : "gold"
|
|
},
|
|
{
|
|
"second place" : "silver"
|
|
},
|
|
{
|
|
"third place" : "bronze"
|
|
}
|
|
]
|
|
}
|
|
]]>
|
|
</screen>
|
|
|
|
<para>
|
|
Still ignoring that this is an array, we can use dot notation to query the
|
|
subobject:
|
|
</para>
|
|
|
|
<example xml:id="mongo.queries.querying-arrays-nested">
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$cursor = $collection->find(array("awards.first place" => "gold"));
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<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>
|
|
|
|
<example xml:id="mongo.queries.querying-arrays-in">
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$cursor = $collection->find(array("awards" => array('$in' => array("gold", "copper"))));
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</simplesect>
|
|
|
|
<simplesect role="changelog">
|
|
&reftitle.changelog;
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<!--
|
|
<row>
|
|
<entry>1.3.1</entry>
|
|
<entry>
|
|
Several database commands can now be executed on secondaries.
|
|
</entry>
|
|
</row>
|
|
-->
|
|
<row>
|
|
<entry>1.3.0</entry>
|
|
<entry>
|
|
Introduced the <link linkend="mongo.readpreferences">Read
|
|
Preferences</link> framework to allow more fine grained control over
|
|
secondary reads.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1.3.0</entry>
|
|
<entry>
|
|
Deprecated <literal>slaveOkay</literal> usage, the alternative is <link
|
|
linkend="mongo.readpreferences">Read Preferences</link>.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1.1.0</entry>
|
|
<entry>
|
|
Introduced the possiblity of routing reads to secondaries of replica set
|
|
members using <methodname>Mongo::setSlaveOkay</methodname>
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</simplesect>
|
|
|
|
</chapter>
|
|
|
|
<!-- 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
|
|
-->
|
|
|