Типы

Содержание

MongoDB позволяет программистам сохранять и запрашивать данные, выраженные во всех основных типах PHP, составных типах (массивы, ассоциативные массивы и объекты) и полдюжины классов, предоставляемых драйвером PHP MongoDB (для регулярных выражений, дат и другие специализированные приложения).

Логиечские и null

true, false, и null могут использоваться как есть.

Числа

Числа отличаются от строк в MongoDB: "123" не соответствует 123. Таким образом, если вы хотите убедиться, что числа отсортированы и сопоставлены правильно, вы должны убедиться, что они действительно сохраняются, как числа.

<?php

$doc 
= array("a" => 123"b" => "123");
$collection->insert($doc);

$doc->find(array("a" => 123));   // совпадает
$doc->find(array("a" => "123")); // не совпадает
$doc->find(array("a" => 123.0)); // совпадает
$doc->find(array("b" => 123));   // не совпадает
$doc->find(array("b" => "123")); // совпадает

?>

Как отмечено выше, числа с плавающей запятой сравниваются с целыми числами или совпадают с ними, как и следовало ожидать.

Большие числа

По умолчанию, в 32-разрядной системе числа отправляются в базу данных, как 32-разрядные целые числа. В 64-битной системе они отправляются, как 64-битные целые числа. Для обратной совместимости все системы десериализуют 64-битные целые числа, как числа с плавающей запятой. Числа с плавающей точкой не являются точными. Если вам нужны точные значения, вы должны изменить настройки php.ini.

В 32-битной системе, если установлен mongo.long_as_object, 64-битные целые числа будут возвращены, как объекты MongoInt64. Целое число будет сохранено в поле значения с идеальной точностью (в виде строки). Вы также можете использовать MongoInt64 для сохранения 64-разрядных целых чисел на 32-разрядных компьютерах.

В 64-битных системах вы можете установить mongo.long_as_object или mongo.native_long. mongo.native_long вернет 64-битные целые и "нормальные" целые числа PHP. Вы можете использовать MongoInt32 для сохранения 32-разрядных целых чисел на 64-разрядных компьютерах.

Вам следует установить поведение mongo.long_as_object и mongo.native_long, которое вы планируете использовать, даже если это поведение по умолчанию (для защиты от будущих изменений по умолчанию).

Смотрите также: параметры php.ini, MongoInt32, MongoInt64.

Строки

Строки должны быть UTF-8. Строки не-UTF-8 должны быть либо преобразованы в UTF-8 перед отправкой в базу данных, либо сохранены, как двоичные данные.

Регулярные выражения могут использоваться для сопоставления строк и выражаются с использованием класса MongoRegex.

Двоичные данные

Строки, изображения и любые другие двоичные данные не в формате UTF-8 следует отправлять в базу данных с использованием типа MongoBinData.

Даты

Даты могут быть созданы с помощью класса MongoDate. Они хранятся в миллисекундах с начала Unix-эпохи.

MongoTimestamp не предназначен для сохранения дат или временных меток, он используется внутри MongoDB. Если вы не создаете инструмент, взаимодействующий с внутренними компонентами репликации или шардинга, вы должны использовать MongoDate, а не MongoTimestamp.

Уникальные идентификаторы

Драйвер автоматически создаст поле _id перед вставкой документа (если он не указан пользователем). Это поле является экземпляром MongoId (в большинстве других языков называется "ObjectId").

Эти идентификаторы имеют длину 12 байтов и состоят из:

  • 4 байта метки времени

    Никакие две записи не могут иметь одинаковый идентификатор, если они были вставлены в разное время.

  • 3-х байтовый идентификатор машины

    Никакие две записи не могут иметь одинаковый идентификатор, если они были вставлены на разных компьютерах.

  • 2-х байтовый идентификатор потока

    Никакие две записи не могут иметь одинаковый идентификатор, если они были вставлены разными потоками, работающими на одной машине.

  • 3 байта значения приращения

    Каждый раз, когда создается идентификатор, глобальный счетчик увеличивается и используется в качестве значения приращения следующего идентификатора.

Таким образом, никакие две записи не могут иметь одинаковый идентификатор, если только одному процессу на одном компьютере не удалось вставить 256^3 (более 16 миллионов) документов за одну секунду, переполнив поле приращения.

JavaScript

MongoDB поставляется с механизмом JavaScript, так что вы можете встраивать JavaScript в запросы (используя предложение $where), отправлять его непосредственно в базу данных для выполнения и использовать для выполнения агрегации.

В целях безопасности используйте поле scope MongoCode, чтобы использовать переменные PHP в JavaScript. Код, который не требует внешних значений, может использовать MongoCode или просто быть строкой. Смотрите раздел о безопасности для получения дополнительной информации об отправке JavaScript в базу данных.

Массивы и Объекты

Массивы и объекты также могут быть сохранены в базе данных. Массив с восходящими числовыми ключами будет сохранен, как массив, все остальное – как объект.

<?php

// $scores будет сохранен, как массив
$scores = array(981007385);
$collection->insert(array("scores" => $scores));

// $scores будет сохранен, как объект
$scores = array("quiz1" => 98"midterm" => 100"quiz2" => 73"final" => 85);
$collection->insert(array("scores" => $scores));

?>

Если вы запросите эти объекты с помощью оболочки базы данных, они будут выглядеть так:

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

База данных также может сохранять произвольные объекты PHP (хотя они будут возвращаться в виде ассоциативных массивов). Поля используются для пар ключ/значение. Например, сообщение в блоге может выглядеть так:

<?php

  
// класс сообщения в блоге
  
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;
  }
}

// создаем простую запись в блоге и вставляем ее в базу данных
$post1 = new Post("Adam""This is a blog post");

$blog->insert($post1);


// нет ничего ограничивающего тип поля "автор", 
// поэтому мы можем сделать его вложенным объектом
$author = array("name" => "Fred""karma" => 42);
$post2 = new Post($author"This is another blog post.");

// мы создаем дополнительное поле, устанавливая заголовок
$post2->setTitle("Second Post");

$blog->insert($post2);

?>

Из оболочки базы данных это будет выглядеть примерно так:

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

Драйвер не будет обнаруживать эталонные циклы в массивах и объектах. Например, это выдаст фатальную ошибку:

<?php

$collection
->insert($GLOBALS);

?>
Fatal error: Nesting level too deep - recursive dependency?
Если вам нужно вставить документы, которые могут иметь рекурсивную зависимость, вы должны проверить их самостоятельно, прежде чем передавать их драйверу.