0

我试图了解使用 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 中进行交叉检查吗?

4

1 回答 1

1

Cross-referencing this question with PHP-841. From the PHP side of things, you're actually storing a BSON code value in the qid field. You can likely verify that when fetching results back from the database or doing a database export with the mongodump command.

The issue is with the JS shell wrongfully evaluating the code type upon display, and that's the point where findAndModify is executed. This fix should be included in a subsequent server release.

In the meantime, Sammaye's suggestion to call findAndModify from PHP is the best option for this sort of functionality. Coincidentally, it is also what is done in Doctrine MongoDB ODM (see: IncrementGenerator). It does require an additional round trip to the server, but that is necessary since MongoDB has no facility for executing JS callbacks during a write operation.

If minimizing the round-trips to MongoDB is of utmost importance, you could insert the documents by executing server-side JS through PHP with MongoDB::execute() and do something like returning the generated ID(s) as the command response. Of course, that's generally not advisable and JS evaluation has its own caveats.

于 2013-06-24T20:30:25.520 回答