MongoDB 没有像 SQL 一样有自动增长的功能, MongoDB 的 _id 是系统自动生成的12字节唯一标识。
但在某些情况下,我们可能需要实现 ObjectId 自动增长功能。
由于 MongoDB 没有实现这个功能,我们可以通过编程的方式来实现,以下我们将在 counters 集合中实现_id字段自动增长。
- 首先需要建立一个表结构,用于存储你的id信息:
db.counters.insert(
{
_id: "userid",
seq: 0
}
)
- 然后定义一个函数,每次调用实现id++功能
我们创建函数 getNextSequence 来作为序列名的输入, 指定的序列会自动增长 1 并返回最新序列值。
在本文的实例中序列名为
userid
function getNextSequence(name) {
varret= db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
上面的函数,主要用到了findAndModify这个系统函数,此系统函数其实就是实现了update的query语句。
拥有类似事务特性的更新与查询操作——findAndModify.
它是原子性的,会返回符合查询条件的更新后的文档。
db.COLLECTION_NAME.findAndModify({query:{},
update:{},
remove:true|false,
new:true|false,
sort:{},
fields:{},
upsert:true|false});
query是查询选择器,与findOne的查询选择器相同
update是要更新的值,不能与remove同时出现
remove表示删除符合query条件的文档,不能与update同时出现
new为true:返回个性后的文档,false:返回个性前的,默认是false
sort:排序条件,与sort函数的参数一致。
fields:投影操作,与find*的第二个参数一致。
upsert:与update的upsert参数一样。
不论是update的第二个参数,还是findAndModify的update,在不指定更新操作符的情况下,将会用指定的新值替换旧值。
比如,
use iteye;
db.blog.update({_id:ObjectId('......')},{title:'new title'});
//上面的操作就把指定_id的文档的标题改成了‘new title’
如果指定了更新操作符,就可以实现更复杂灵活的更新操作。
可以通过更新操作符,增加或减少数值,针对数组类型的属性,做类似队列或栈的操作。
单从这一点来说,mongo要比sql数据库强大的多了。
- 接下来就可以在其他集合中进行应用了
- 插入单条
db . users . insert (
{
_id: getNextSequence("userid"),
name: "FLY"
}
)
- 输出结果:
/* 1 */
{
"_id" : 1.0,
"name" : "FLY"
}
- 插入多条
db.users.insertMany([
{
_id: getNextSequence("userid"),
name: "QQ"
},
{
_id: getNextSequence("userid"),
name: "Wechat"
},
{
_id: getNextSequence("userid"),
name: "WeiBo"
}
])
- 输出结果
/* 1 */
{
"acknowledged" : true,
"insertedIds" : [
2.0,
3.0,
4.0
]
}
/* 1 */
{
"_id" : 1.0,
"name" : "FLY"
}
/* 2 */
{
"_id" : 2.0,
"name" : "QQ"
}
/* 3 */
{
"_id" : 3.0,
"name" : "Wechat"
}
/* 4 */
{
"_id" : 4.0,
"name" : "WeiBo"
}
注意:
- 按照上面的方法,有一个问题。就是每次退出mongo重进之后,我的getNextSequence都无法正常使用了,会出现下面所示的错误:
Failed to execute script.
Error:
ReferenceError: getNextSequence is not defined :
@(shell):3:6
原因分析:
本实例中定义的函数没有保存,在mongo实例退出后会自动清零。所以需要对我们辛辛苦苦定义的函数进行保存,要不然岂不是白干了。
那好我们就保存在一个表中,这样总不至于把函数搞丢了吧。
- 保存的方式也有两种,一种是插入
db.system.js.insert({
_id:"getNextSequence",
value:function getNextSequence(name) {
varret= db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
});
- 还有一种保存方法,在官网上有提到,就是用db.collection.save()函数进行保存,其实都是一样的。
db.system.js.save({
_id : "myAddFunction" ,
value : function (name){
varret= db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
});
可能有人会问,为什么是system.js这个表,而不是其他的,因为这个表是专门用来保存js函数的。
如果你定义完函数退出mongo实例,会发现还是无法使用函数getNextSequence,
这是因为虽然你定义了函数,但是没有把函数引入进来,也就是说每次重新进入mongo的实例后需要把相应的js函数重新导入一遍
通过,db.loadServerScripts();把system.js中的函数,引入到mongo实例。
这也是保存到system.js中原因,mongodb数据库提供了很好的库函数进行函数引用。
还有一种引入方式如下:
db.eval(‘getNextSequence(“userid”)’);
db.loadServerScripts()
db.users.insert(
{
_id: getNextSequence("userid"),
name: "DD"
}
)
参考来源:http://blog.csdn.net/baiyvwuxia/article/details/47274243