MongoDB:21-MongoDB-自增Id

来源:互联网 发布:php的配置文件在哪里 编辑:程序博客网 时间:2024/06/15 11:13
  1. MongoDB 没有像 SQL 一样有自动增长的功能, MongoDB _id 是系统自动生成的12字节唯一标识。
  2. 但在某些情况下,我们可能需要实现 ObjectId 自动增长功能
  3. 由于 MongoDB 没有实现这个功能,我们可以通过编程的方式来实现,以下我们将在 counters 集合中实现_id字段自动增长。
  1. 首先需要建立一个表结构,用于存储你的id信息:
    1. db.counters.insert(
    2. {
    3. _id: "userid",
    4. seq: 0
    5. }
    6. )

  2. 然后定义一个函数,每次调用实现id++功能
    1. 我们创建函数 getNextSequence 来作为序列名的输入, 指定的序列会自动增长 1 并返回最新序列值。
    2. 在本文的实例中序列名为 userid

    1. function getNextSequence(name) {
    2. var ret = db.counters.findAndModify(
    3. {
    4. query: { _id: name },
    5. update: { $inc: { seq: 1 } },
    6. new: true
    7. }
    8. );
    9. return ret.seq;
    10. }
    1. 上面的函数,主要用到了findAndModify这个系统函数,此系统函数其实就是实现了updatequery语句。
    1. 拥有类似事务特性的更新与查询操作——findAndModify.
    2. 它是原子性的,会返回符合查询条件的更新后的文档。
    3. db.COLLECTION_NAME.findAndModify({query:{},
    4. update:{},
    5. remove:true|false,
    6. new:true|false,
    7. sort:{},
    8. fields:{},
    9. upsert:true|false});
    10. query是查询选择器,与findOne的查询选择器相同
    11. update是要更新的值,不能与remove同时出现
    12. remove表示删除符合query条件的文档,不能与update同时出现
    13. newtrue:返回个性后的文档,false:返回个性前的,默认是false
    14. sort:排序条件,与sort函数的参数一致。
    15. fields:投影操作,与find*的第二个参数一致。
    16. upsert:与updateupsert参数一样。
    17. 不论是update的第二个参数,还是findAndModifyupdate,在不指定更新操作符的情况下,将会用指定的新值替换旧值。
    18. 比如,
    19. use iteye;
    20. db.blog.update({_id:ObjectId('......')},{title:'new title'});
    21. //上面的操作就把指定_id的文档的标题改成了‘new title’
    22. 如果指定了更新操作符,就可以实现更复杂灵活的更新操作。
    23. 可以通过更新操作符,增加或减少数值,针对数组类型的属性,做类似队列或栈的操作。
    24. 单从这一点来说,mongo要比sql数据库强大的多了。

  3. 接下来就可以在其他集合中进行应用了    
  • 插入单条
    1. db.users.insert(
    2. {
    3. _id: getNextSequence("userid"),
    4. name: "FLY"
    5. }
    6. )
    输出结果:
    1. /* 1 */
    2. {
    3. "_id" : 1.0,
    4. "name" : "FLY"
    5. }
  • 插入多条
    1. db.users.insertMany([
    2. {
    3. _id: getNextSequence("userid"),
    4. name: "QQ"
    5. },
    6. {
    7. _id: getNextSequence("userid"),
    8. name: "Wechat"
    9. },
    10. {
    11. _id: getNextSequence("userid"),
    12. name: "WeiBo"
    13. }
    14. ])
    输出结果
    1. /* 1 */
    2. {
    3. "acknowledged" : true,
    4. "insertedIds" : [
    5. 2.0,
    6. 3.0,
    7. 4.0
    8. ]
    9. }
    1. /* 1 */
    2. {
    3. "_id" : 1.0,
    4. "name" : "FLY"
    5. }
    6. /* 2 */
    7. {
    8. "_id" : 2.0,
    9. "name" : "QQ"
    10. }
    11. /* 3 */
    12. {
    13. "_id" : 3.0,
    14. "name" : "Wechat"
    15. }
    16. /* 4 */
    17. {
    18. "_id" : 4.0,
    19. "name" : "WeiBo"
    20. }
注意:
  1. 按照上面的方法,有一个问题。就是每次退出mongo重进之后,我的getNextSequence都无法正常使用了,会出现下面所示的错误:
    1. Failed to execute script.
    2. Error:
    3. ReferenceError: getNextSequence is not defined :
    4. @(shell):3:6

原因分析:
  1. 本实例中定义的函数没有保存,在mongo实例退出后会自动清零。所以需要对我们辛辛苦苦定义的函数进行保存,要不然岂不是白干了。
  2. 那好我们就保存在一个表中,这样总不至于把函数搞丢了吧。
  • 保存的方式也有两种,一种是插入
  1. db.system.js.insert({
  2. _id:"getNextSequence",
  3. value:function getNextSequence(name) {
  4. var ret = db.counters.findAndModify(
  5. {
  6. query: { _id: name },
  7. update: { $inc: { seq: 1 } },
  8. new: true
  9. }
  10. );
  11. return ret.seq;
  12. }
  13. });

 
  • 还有一种保存方法,在官网上有提到,就是用db.collection.save()函数进行保存,其实都是一样的。
    1. db.system.js.save({
    2. _id : "myAddFunction" ,
    3. value : function (name){
    4. var ret = db.counters.findAndModify(
    5. {
    6. query: { _id: name },
    7. update: { $inc: { seq: 1 } },
    8. new: true
    9. }
    10. );
    11. return ret.seq;
    12. }
    13. });


  1. 可能有人会问,为什么是system.js这个表,而不是其他的,因为这个表是专门用来保存js函数的。
  2. 如果你定义完函数退出mongo实例,会发现还是无法使用函数getNextSequence,
  3. 这是因为虽然你定义了函数,但是没有把函数引入进来,也就是说每次重新进入mongo的实例后需要把相应的js函数重新导入一遍
  1. 通过,db.loadServerScripts();把system.js中的函数,引入到mongo实例。
  2. 这也是保存到system.js中原因,mongodb数据库提供了很好的库函数进行函数引用。
  1. 还有一种引入方式如下:
  2. db.eval(‘getNextSequence(“userid”)’);
  1. db.loadServerScripts()
  2. db.users.insert(
  3. {
  4. _id: getNextSequence("userid"),
  5. name: "DD"
  6. }
  7. )
参考来源:http://blog.csdn.net/baiyvwuxia/article/details/47274243

原创粉丝点击