我正在尝试使用PHP与mongodb 2.4.3 win32来理解一个奇怪的行为。 我尝试让服务器端生成序列ID。
使用存储函数作为参数之一插入文档时,似乎每次插入时都会多次调用存储的函数。
假设我有一个像这样初始化的计数器:
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仍然需要确保我们在内部mongodb存储中有64位无符号整数吗?任何在shell中交叉检查的命令?
答案 0 :(得分:1)
使用PHP-841交叉引用此问题。从PHP方面来看,您实际上是在qid
字段中存储BSON code value。您可以验证从数据库中取回结果或使用mongodump
命令执行数据库导出时。
问题在于JS shell在显示时错误地评估了代码类型,这就是执行findAndModify
的点。此修复程序应包含在后续服务器版本中。
与此同时,Sammaye建议从PHP调用findAndModify
是这类功能的最佳选择。巧合的是,它也是在Doctrine MongoDB ODM中完成的(参见:IncrementGenerator)。它确实需要额外的往返服务器,但这是必要的,因为MongoDB在写操作期间没有执行JS回调的工具。
如果最小化到MongoDB的往返是最重要的,您可以通过PHP MongoDB::execute()执行服务器端JS来插入文档,并执行类似返回生成的ID作为命令响应的操作。当然,这通常是不可取的,JS评估有其自己的警告。