# Types

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

## Booleans and &null;

&true;, &false;, and &null; can be used as-is.

## Numbers

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.

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

    ?>

As noted above, floating point numbers do compare with/match integer numbers as one would expect.

### Large Numbers

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 php.ini settings.

On a 32-bit system, if `mongo.long_as_object` is set, 64-bit integers will be returns as `MongoInt64` objects. The integer will be stored in the `value` field with perfect precision (as a string). You can also use `MongoInt64` to save 64-bit integers on 32-bit machines.

On 64-bit systems, you can either set `mongo.long_as_object` or set `mongo.native_long`. `mongo.native_long` will return 64-bit integers and "normal" PHP integers. You can use `MongoInt32` to save 32-bit integers on 64-bit machines.

You should set the `mongo.long_as_object` and `mongo.native_long` behavior that you plan to use, even if it is the default behavior (to protect against future changes to the defaults).

See also: php.ini Options, `MongoInt32`, `MongoInt64`.

## Strings

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.

Regular expressions can be used to match strings, and are expressed using the `MongoRegex` class.

## Binary Data

Non-UTF-8 strings, images, and any other binary data should be sent to the database using the `MongoBinData` type.

## Dates

Dates can be created using the `MongoDate` class. They are stored as milliseconds since the epoch.

`MongoTimestamp` 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 `MongoDate`, not `MongoTimestamp`.

## Unique Ids

The driver will automatically create an `_id` field before inserting a document (unless one is specified by the user). This field is an instance of `MongoId` (called "ObjectId" in most other languages).

These ids are 12 bytes long and composed of:

- 4 bytes of timestamp

  No two records can have the same id if they were inserted at different times.

- 3 bytes machine id

  No two records can have the same id if they were inserted on different machines

- 2 bytes thread id

  No two records can have the same id if they were inserted by different threads running on the same machine.

- 3 bytes incrementing value

  Each time an id is created, a global counter is incremented and used as the increment value of the next id.

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.

## JavaScript

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.

For security, use `MongoCode`'s `scope` field to use PHP variables in JavaScript. Code that does not require external values can either use `MongoCode` or just be a string. See the section on security for more information about sending JavaScript to the database.

## Arrays and Objects

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.

    <?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));

    ?>

If you query for these objects using the database shell, they will look like:

    > db.students.find()
    { "_id" : ObjectId("4b06beada9ad6390dab17c43"), "scores" : [ 98, 100, 73, 85 ] }
    { "_id" : ObjectId("4b06bebea9ad6390dab17c44"), "scores" : { "quiz1" : 98, "midterm" : 100, "quiz2" : 73, "final" : 85 } }

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:

    <?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);

    ?>

From the database shell, this will look something like:

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

The driver will not detect reference loops in arrays and objects. For example, this will give a fatal error:

    <?php

    $collection->insert($GLOBALS);

    ?>

    Fatal error: Nesting level too deep - recursive dependency?

If you need to insert documents that may have recursive dependency, you have to check for it yourself before passing it to the driver.
&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;