Как я могу принудительно сохранить числовое значение NumberLong() в mongo с помощью драйвера php mongo?

#php #mongodb

#php #mongodb

Вопрос:

У меня есть API, который ожидает, что определенное поле будет иметь NumberLong значения. Поэтому при записи в базу данных with с помощью драйвера PHP эти значения должны быть записаны как type NumberLong . Здесь говорится , что

Когда драйвер кодирует целое число PHP в BSON (здесь ), мы используем макрос, который записывает 64-разрядное или 32-разрядное целое число в зависимости от диапазона целочисленного значения PHP. Это аналогично поведению сервера, где результаты вычисления целых чисел (например, из $inc ) будут использовать наименьший тип, способный содержать значение, и при необходимости переходить к большому типу.

Насколько я могу судить, это все еще так.

Эта программа воссоздает проблему:

 // document with _id=0 looks like: {"_id": 0, "number": NumberLong(42)}
$collection = (new DBMongo())->selectCollection("test");
$docs = $collection->find(["_id" => 0]);
foreach ($docs as $doc) {
  $doc["_id"] = 1;
  $doc["number"] = 42;
  $collection->insertOne($doc);
}
// document with _id=1 looks like: {"_id": 1, "number": 42}
 

Цель состоит в том, чтобы «скопировать» некоторые документы, внеся простые изменения. PHP используется по историческим причинам.

Как я могу заставить "number" поле в приведенном выше документе _id=1 быть NumberLong(42) таким, какое оно есть с _id= 0 ?

Комментарии:

1. Это кажется невозможным.

2. Это довольно обескураживающе слышать.

Ответ №1:

Я проанализировал некоторый расширенный json с помощью драйвера php, и информация о типе была потеряна, что привело меня к мысли, что драйвер не предоставляет простого способа сохранения типов. Int64 содержит примечание о том, что оно не может быть создано напрямую.

С учетом сказанного, драйвер технически не обязан сохранять информацию о типе для своей собственной функциональности, за исключением идентификаторов курсоров, которые должны быть отправлены на сервер в виде int64. Исходя из этого, я предлагаю следующее:

  • Выполните поиск и получите курсор. Извлеките его идентификатор курсора.
  • Сериализуйте идентификатор курсора. По сути, это int64.
  • Посмотрите на сериализованное представление, чтобы выяснить, где находится значение.
  • Создайте новое сериализованное представление со значением int64, которое вы хотите.
  • Десериализуйте идентификатор курсора из этого представления.
  • Используйте идентификатор курсора в своей операции, куда вы хотите отправить int64.

Несколько сумасшедшая идея, но она может сработать.

Комментарии:

1. Я попробую при первой возможности и сообщу об этом. Спасибо.