Сохраненная функция, используемая во вставке, через PHP работает несколько раз

Я пытаюсь понять странное поведение с помощью PHP с mongodb 2.4.3 win32. Я пытаюсь создать идентификаторы последовательности на стороне сервера.

При вставке документов с использованием сохраненной функции в качестве одного из параметров кажется, что хранимая функция вызывается несколько раз при каждой вставке.

Скажем, у меня есть счетчик, инициализированный следующим образом:

db.counters.insert( { _id: "uqid", seq: NumberLong(0) } ); 

У меня есть хранимая функция с именем getUqid, которая определяется как

 db.system.js.save( { _id: "getUqid", value: function () { var ret = db.counters.findAndModify( { query: { _id: "uqid" }, update: { $inc: { seq: NumberLong(1) } }, new: true } ); return ret.seq; } } ); 

Когда я делаю три вставки, например:

 $conn->test->ads->insert(['qid' => new MongoCode('getUqid()') , 'name' => "Sarah C."]); 

Я получаю что-то вроде этого:

 db.ads.find() { "_id" : ObjectId("51a34f8bf0774cac03000000"), "qid" : 17, "name" : "Sarah C." } { "_id" : ObjectId("51a34f8bf0774cac03000001"), "qid" : 20, "name" : "Michel D." } { "_id" : ObjectId("51a34f8bf0774cac03000002"), "qid" : 23, "name" : "Robert U." } 

Любая подсказка, почему на QID наступает 3? Это должно означать, что я получил три вызова моей сохраненной функции?

Заранее спасибо за вашу помощь, С уважением.

PS: вторичный вопрос: нужны ли NumberLong, чтобы убедиться, что у нас есть 64-битное целое число без знака во внутреннем хранилище mongodb? Любая команда для перекрестной проверки этого в оболочке?

Перекрестный ссылки на этот вопрос с помощью PHP-841 . С точки зрения PHP вы фактически сохраняете значение кода BSON в поле qid . Вероятно, вы можете убедиться, что при извлечении результатов из базы данных или при экспорте базы данных с mongodump команды mongodump .

Проблема заключается в том, что оболочка JS неправомерно оценивает тип кода при отображении, и это то место, где findAndModify . Это исправление должно быть включено в последующую версию сервера.

Тем временем, предложение findAndModify вызвать findAndModify из PHP – лучший вариант для такого рода функций. Кстати, это также то, что сделано в Doctrine MongoDB ODM (см .: IncrementGenerator ). Для этого требуется дополнительная обратная поездка на сервер, но это необходимо, поскольку MongoDB не имеет возможности для выполнения обратных вызовов JS во время операции записи.

Если минимизировать круговые поездки в MongoDB, вы можете вставить документы, выполнив JS на стороне сервера через PHP с помощью MongoDB :: execute () и сделайте что-то вроде возврата сгенерированных идентификаторов (ID) в качестве ответа команды. Конечно, это обычно нецелесообразно, и оценка JS имеет свои собственные оговорки.