MongoDB:21-MongoDB-自增Id

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: MongoDB:21-MongoDB-自增Id


  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. )


  1. 然后定义一个函数,每次调用实现id++功能


  1. 我们创建函数 getNextSequence 来作为序列名的输入, 指定的序列会自动增长 1 并返回最新序列值。
  2. 在本文的实例中序列名为 userid


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


  1. 接下来就可以在其他集合中进行应用了    

  • 插入单条
  1.       db        .        users        .        insert        (
  2.   {
  3.     _id: getNextSequence("userid"),
  4.     name: "FLY"
  5.   }
  6. )
  1. 输出结果:
  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. /* 1 */
  2. {
  3.    "acknowledged" : true,
  4.    "insertedIds" : [
  5.        2.0,
  6.        3.0,
  7.        4.0
  8.    ]
  9. }
  10. /* 1 */
  11. {
  12.    "_id" : 1.0,
  13.    "name" : "FLY"
  14. }
  15. /* 2 */
  16. {
  17.    "_id" : 2.0,
  18.    "name" : "QQ"
  19. }
  20. /* 3 */
  21. {
  22.    "_id" : 3.0,
  23.    "name" : "Wechat"
  24. }
  25. /* 4 */
  26. {
  27.    "_id" : 4.0,
  28.    "name" : "WeiBo"
  29. }


注意:

  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.   varret= db.counters.findAndModify(
  5.          {
  6.            query: { _id: name },
  7.            update: { $inc: { seq: 1 } },
  8.            new: true
  9.          }
  10.   );
  11.   return ret.seq;
  12. }
  13. });

图片.png

 

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


图片.png

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

参考来源:http://blog.csdn.net/baiyvwuxia/article/details/47274243



相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
NoSQL MongoDB 数据库
分布式服务器框架之Server.Core库中实现YFUniqueEntity、YFUniqueIDBase 管理MongoDB 自定义Id的自增
YFUniqueEntity是数据库中的结构,GetUniqueID函数中会根据Type和自增步长去数据库中寻找该类型的当前ID是多少,然后会用当前的Id去加上步长,把更新后的新ID插入到MongoDB中记录着ID的那张表里。
|
SQL NoSQL MongoDB
分布式服务器框架之Servers.Core库中实现MongoDB对象实体类 管理对象ID
MongoDB中的ID是一个hash码,和传统的关系数据库相比MongoDB没有办法实现ID的自增,如果需要ID自增的话,所以要自己管理ID,并且把对应类型的ID写入到一个专门的Collection(其实就是Sql中的Table)里面去,每次创建新对象的时候,都要取到该类型当前的ID,然后在这个基础上+1,比如当前是角色的ID是1,又创建了一个新的角色,要在原来的基础上+1 ID=2。今天先把MongoDB的对象实体基类实现了。
|
存储 NoSQL Unix
mongodb出现重复id怎么办?
mongodb出现重复id怎么办?
438 0
|
JSON NoSQL Java
在java项目中的mongodb的_id被fastjson转为json时竟然丢失了
fastjson是阿里开发的一个javaBean和json解析器和封装器(源码位置),用过几次感觉挺好用的,也是国人的开源项目当然得支持,但最近项目在使用mongodb作为数据库时出现了_id丢失的问题,现将我遇到的问题和解决办法展示一下。 现将错误的程序代码添加上,然后再提供解决方法: package org.jivesoftware.openfire.plugin.f
2923 0
|
3天前
|
存储 NoSQL MongoDB
MongoDB如何创建数据库
MongoDB如何创建数据库
|
3天前
|
JSON NoSQL MongoDB
理解Nosql数据库的mongodb
【5月更文挑战第5天】MongoDB是2009年发布的一款通用型NoSQL数据库,结合了关系模型和NoSQL的优点,适用于各种现代应用。其特点包括图形界面、数据服务、云基础设施集成(AWS, Azure, Google Cloud)。它具备全面的查询能力、ACID事务、可调整的一致性保证,并有多语言驱动及工具,可在任何地方运行。
42 4