1、实现原理
假设要为CollectionB实现自增ID,,需要引入另外一个计算“_id”的CollectionA。
CollectionA中存放一条记录:{'_id':'CollectionB', 'currentIdValue':1}, 其中currentIdValue表示CollectionB的当前最大id值+1,每次往CollectionB里插入数据前,先到CollectionA查询currentIdValue 值并把这个值+1
从上面的原理,需要一个查询并加1的原子操作,mongodb提供了这样的接口,而且是线程安全的,即是findAndModify。
2、Mongo命令示例
mongodb的脚本如下:
db.runCommand(findAndModify:'CollectionA',query:{_id:'CollectionB'}, update:{$inc:{'currentIdValue':1}}, new:true};
查询与更新,查询'CollectionA'表_id为'CollectionB'的内容,并将'currentIdValue'属性值+1,返回该内容
3、C++示例
MongoDB.h文件
using namespace mongo; // 8小时 #define UTC_TIME_ZONE 28800000 class MongoDB { public: // 数据库名称 static string mNameDB; static BOOL connectDB(string conText,string dbName); // 数据库链接 static DBClientConnection mMongoConn; static int getMid(string db); };
MongoDB.cpp文件
#include "MongoDB.h" // 静态MONGO链接声明 DBClientConnection MongoDB::mMongoConn; string MongoDB::mNameDB; BOOL MongoDB::connectDB(string conText,string dbName) { MongoDB::mNameDB = dbName; string strErr; // 链接数据库 if(!MongoDB::mMongoConn.connect(conText,strErr)) { /*TRACE("DB connect ERROR %s\r\n",strErr);*/ return FALSE; } // 登陆数据库 if(!MongoDB::mMongoConn.auth(dbName,"admin","aaa111+++",strErr)) { //TRACE("DB auth ERROR %s\r\n",strErr); return FALSE; } return TRUE; }
// 返回自增ID (表不存在自动补表) int MongoDB::getMid(string db) { string err; BSONObj b; BSONObjBuilder bj; // 当前集合Collection bj.append("findAndModify","Collection"); // 查询串 bj.append("query",BSON("_id"<<db)); // 更新串 bj.append("update",BSON("$inc"<<BSON("currentIdValue"<<1))); MongoDB::mMongoConn.runCommand(MongoDB::mNameDB,bj.obj(),b); err = MongoDB::mMongoConn.getLastError(); if(!err.empty()) return 0; // 获取返回内容 BSONElement bel = b.getField("value"); if(bel.isNull()) { int tmp = 1; // 数据库不存在记录,创建自增ID MongoDB::mMongoConn.insert(mNameDB + ".Collection", BSON("_id"<<db<<"currentIdValue"<<tmp)); err = MongoDB::mMongoConn.getLastError(); if(err.empty()) { return 1; } return 0; } // 当EL是结束 if(bel.eoo()) return 0; // 检查类型是INT或DOUBLE if(bel.type() == mongo::NumberDouble) return (int)bel["currentIdValue"].Double(); else return bel["currentIdValue"].Int(); }