通过PHP插入时使用的存储函数运行多次

时间:2013-05-27 13:03:50

标签: php mongodb

我正在尝试使用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中交叉检查的命令?

1 个答案:

答案 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评估有其自己的警告。