php-doc-en/reference/mongo/types.xml
Christoph Michael Becker e6ea4d8d68 fixed broken/incorrect links
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@338676 c90b9560-bf6c-de11-be94-00142212c4b1
2016-03-03 08:44:35 +00:00

317 lines
9.8 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<part xml:id="mongo.types" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Types</title>
<partintro>
<section>
<para>
MongoDB allows programmers to save and query for data expressed in all of the
basic PHP types, compound types (arrays, associative arrays, and objects), and
a half-dozen classes provided by the MongoDB PHP driver (for regular
expressions, dates, and other specialized applications).
</para>
</section>
<section>
<title>Booleans and &null;</title>
<para>
&true;, &false;, and &null; can be used as-is.
</para>
</section>
<section>
<title>Numbers</title>
<para>
Numbers are distinct from strings in MongoDB: "123" does not match 123.
Thus, if you want to make sure numbers are sorted and matched correctly, you
must make sure that they are actually saved as numbers.
</para>
<programlisting role="php">
<![CDATA[
<?php
$doc = array("a" => 123, "b" => "123");
$collection->insert($doc);
$doc->find(array("a" => 123)); // matches
$doc->find(array("a" => "123")); // doesn't match
$doc->find(array("a" => 123.0)); // matches
$doc->find(array("b" => 123)); // doesn't match
$doc->find(array("b" => "123")); // matches
?>
]]>
</programlisting>
<para>
As noted above, floating point numbers do compare with/match integer numbers
as one would expect.
</para>
<section>
<title>Large Numbers</title>
<para>
By default, on a 32-bit system, numbers are sent to the database as 32-bit
integers. On a 64-bit system, they are sent as 64-bit integers. For
backwards compatibility, all systems deserialize 64-bit integers as floating
point numbers. Floating point numbers are not exact. If you need exact
values, you must tweak your
<link linkend="mongo.configuration">php.ini settings</link>.
</para>
<para>
On a 32-bit system, if <literal>mongo.long_as_object</literal> is set,
64-bit integers will be returns as <classname>MongoInt64</classname>
objects. The integer will be stored in the <literal>value</literal> field
with perfect precision (as a string). You can also use
<classname>MongoInt64</classname> to save 64-bit integers on 32-bit
machines.
</para>
<para>
On 64-bit systems, you can either set <literal>mongo.long_as_object</literal>
or set <literal>mongo.native_long</literal>.
<literal>mongo.native_long</literal> will return 64-bit integers and
"normal" PHP integers. You can use <classname>MongoInt32</classname> to
save 32-bit integers on 64-bit machines.
</para>
<para>
You should set the <literal>mongo.long_as_object</literal> and
<literal>mongo.native_long</literal> behavior that you plan to use, even if
it is the default behavior (to protect against future changes to the
defaults).
</para>
<para>
See also: <link linkend="mongo.configuration">php.ini Options</link>,
<classname>MongoInt32</classname>, <classname>MongoInt64</classname>.
</para>
</section>
</section>
<section>
<title>Strings</title>
<para>
Strings must be UTF-8. Non-UTF-8 strings must either be converted to UTF-8
before being sent to the database or saved as binary data.
</para>
<para>
Regular expressions can be used to match strings, and are expressed using the
<classname>MongoRegex</classname> class.
</para>
</section>
<section>
<title>Binary Data</title>
<para>
Non-UTF-8 strings, images, and any other binary data should be sent to the
database using the <classname>MongoBinData</classname> type.
</para>
</section>
<section>
<title>Dates</title>
<para>
Dates can be created using the <classname>MongoDate</classname> class. They
are stored as milliseconds since the epoch.
</para>
<para>
<classname>MongoTimestamp</classname> is not for saving dates or timestamps,
it is used internally by MongoDB. Unless you are creating a tool that
interacts with the internals of replication or sharding, you should use
<classname>MongoDate</classname>, <emphasis>not</emphasis>
<classname>MongoTimestamp</classname>.
</para>
</section>
<section>
<title>Unique Ids</title>
<para>
The driver will automatically create an <literal>_id</literal> field before
inserting a document (unless one is specified by the user). This field is an
instance of <classname>MongoId</classname> (called "ObjectId" in most other
languages).
</para>
<para>
These ids are 12 bytes long and composed of:
<itemizedlist>
<listitem>
<para>4 bytes of timestamp</para>
<para>
No two records can have the same id if they were inserted at different
times.
</para>
</listitem>
<listitem>
<para>3 bytes machine id</para>
<para>
No two records can have the same id if they were inserted on different
machines
</para>
</listitem>
<listitem>
<para>2 bytes thread id</para>
<para>
No two records can have the same id if they were inserted by different
threads running on the same machine.
</para>
</listitem>
<listitem>
<para>3 bytes incrementing value</para>
<para>
Each time an id is created, a global counter is incremented and used
as the increment value of the next id.
</para>
</listitem>
</itemizedlist>
Thus, no two records can have the same id unless a single process on a
single machine managed to insert 256^3 (over 16 million) documents in
one second, overflowing the increment field.
</para>
</section>
<section>
<title>JavaScript</title>
<para>
MongoDB comes with a JavaScript engine, so you can embed JavaScript in
queries (using a $where clause), send it directly to the database to be
executed, and use it to perform aggregations.
</para>
<para>
For security, use <classname>MongoCode</classname>'s <literal>scope</literal>
field to use PHP variables in JavaScript. Code that does not require
external values can either use <classname>MongoCode</classname> or just be
a string. See the
<link linkend="mongo.security">section on security</link> for more
information about sending JavaScript to the database.
</para>
</section>
<section>
<title>Arrays and Objects</title>
<para>
Arrays and objects can also be saved to the database. An array with ascending
numeric keys will be saved as a an array, anything else will be saved as an
object.
</para>
<programlisting role="php">
<![CDATA[
<?php
// $scores will be saved as an array
$scores = array(98, 100, 73, 85);
$collection->insert(array("scores" => $scores));
// $scores will be saved as an object
$scores = array("quiz1" => 98, "midterm" => 100, "quiz2" => 73, "final" => 85);
$collection->insert(array("scores" => $scores));
?>
]]>
</programlisting>
<para>
If you query for these objects using the database shell, they will look like:
<programlisting role="shell">
<![CDATA[
> db.students.find()
{ "_id" : ObjectId("4b06beada9ad6390dab17c43"), "scores" : [ 98, 100, 73, 85 ] }
{ "_id" : ObjectId("4b06bebea9ad6390dab17c44"), "scores" : { "quiz1" : 98, "midterm" : 100, "quiz2" : 73, "final" : 85 } }
]]>
</programlisting>
</para>
<para>
The database can also save arbitrary PHP objects (although they will be
returned as associative arrays). The fields are used for the key/value
pairs. For example, a blog post might look like:
<programlisting role="php">
<![CDATA[
<?php
// the blog post class
class Post {
var $author;
var $content;
var $comments = array();
var $date;
public function __construct($author, $content) {
$this->author = $author;
$this->content = $content;
$this->date = new MongoDate();
}
public function setTitle($title) {
$this->title = $title;
}
}
// create a simple blog post and insert it into the database
$post1 = new Post("Adam", "This is a blog post");
$blog->insert($post1);
// there is nothing restricting the type of the "author" field, so we can make
// it a nested object
$author = array("name" => "Fred", "karma" => 42);
$post2 = new Post($author, "This is another blog post.");
// we create an extra field by setting the title
$post2->setTitle("Second Post");
$blog->insert($post2);
?>
]]>
</programlisting>
</para>
<para>
From the database shell, this will look something like:
<programlisting role="shell">
<![CDATA[
> db.blog.find()
{ "_id" : ObjectId("4b06c263edb87a281e09dad8"), "author" : "Adam", "content" : "This is a blog post", "comments" : [ ], "date" : "Fri Nov 20 2009 11:22:59 GMT-0500 (EST)" }
{ "_id" : ObjectId("4b06c282edb87a281e09dad9"), "author" : { "name" : "Fred", "karma" : 42 }, "content" : "This is a blog post", "comments" : [ ], "date" : "Fri Nov 20 2009 11:23:30 GMT-0500 (EST)", "title" : "Second Post" }
]]>
</programlisting>
</para>
<para>
The driver will not detect reference loops in arrays and objects. For
example, this will give a fatal error:
<programlisting role="php">
<![CDATA[
<?php
$collection->insert($GLOBALS);
?>
]]>
</programlisting>
<programlisting role="txt">
<![CDATA[
Fatal error: Nesting level too deep - recursive dependency?
]]>
</programlisting>
If you need to insert documents that may have recursive dependency, you have
to check for it yourself before passing it to the driver.
</para>
</section>
</partintro>
&reference.mongo.mongoid;
&reference.mongo.mongocode;
&reference.mongo.mongodate;
&reference.mongo.mongoregex;
&reference.mongo.mongobindata;
&reference.mongo.mongoint32;
&reference.mongo.mongoint64;
&reference.mongo.mongodbref;
&reference.mongo.mongominkey;
&reference.mongo.mongomaxkey;
&reference.mongo.mongotimestamp;
</part>