php-doc-en/reference/mongo/queries.xml
Nikita Popov f1e951b988 Remove duplicated words
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
2019-07-14 13:46:42 +00:00

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
-->