MongoDB에서 자동 증가 시퀀스를 만드는 방법
이번에는 MongoDB에서 자동 증가 시퀀스를 만드는 방법에 대해 설명하겠다.
MongoDB는 기본적으로 시퀀스가 존재하지 않기 때문에 따로 코드를 생성을 해야 한다. 여기에서는 간단한 예제로 두 가지 방법을 소개한다.
개요
기본적으로 MongoDB는 다수의 도큐먼트를 다루기 때문에 임의의 필드에 인크리먼트(increment)가 발생하지 않는다. 기본적으로 _id
에 ObjectId
의 고유 키가 생성되므로 이를 사용한다.
그렇다고는 해도 시스템상 독특한 일련번호가 필요한 경우도 있다고 생각된다. 이번에는 독특한 번호를 발번하는 방법을 두 가지 소개한다.
어느 쪽의 방법에 대해서도 아래와 같이 도큐먼트에 userid
에 시퀀스를 발행하는 방법을 예제 코드를 만들어 보기로 하겠다.
- database :
test
- collection :
users
- document :
{userid, name}
카운터 컬렉션을 사용하는 방법
{key: string, seq: number}
포맷으로 counters
컬렉션을 만들어 시퀀스가 필요한 도큐먼트를 등록할 때에 이 counters
도큐먼트로부터 최대치를 조회한 후에 갱신하는 것으로 자동 인크리먼트를 만드는 방법이다.
전제
counters
컬렉션을 생성한다. 다음 예제는 mongo
명령에서 실행한다.
> db.counters.createIndex({ key: 1 }, { unique: true })
> db.counters.insertOne({ key: "userid", seq: 0 })
작성 결과는 다음과 같다.
> db.counters.find({}, { _id: 0 })
{ "key" : "userid", "seq" : 0 }
소스 (index.js)
var MongoClient = require("mongodb").MongoClient;
const CONNECTION_STRING = "mongodb://localhost:27017/test";
// 시퀀스용 코렉션을 이용하여 시퀀스 발행
var insertUser = function (userinfo, callback) {
MongoClient.connect(CONNECTION_STRING).then((db) => {
// 카운트 콜렉션으로 부터 시퀀스 조회
db.collection("counters").findOneAndUpdate(
{ key: "userid" },
{ $inc: { seq: 1 } },
{ upsert: true, returnOriginal: true },
(err, doc) => {
// 시퀀스 변호 설정
userinfo.userid = doc.value.seq;
// 도큐먼트 등록
db.collection("users").insertOne(userinfo, (err, res) => {
callback && callback(err, res);
});
});
}).catch((err) => {
console.log(err.message);
});
};
// 실제 등록하기
insertUser({
name: "kimkc"
});
insertUser({
name: "devkuma"
});
실행
> node ./index.js
결과
> db.users.find({},{_id:0})
{ "name" : "kimkc", "userid" : 0 }
{ "name" : "devkuma", "userid" : 1 }
루프 처리를 이용하는 방법
시퀀스용 콜렉션을 생성하지 않고, 현재 등록된 데이터에서 최대값을 가져와 다음 번호를 가져온다.
소스 (index.js)
var MongoClient = require("mongodb").MongoClient;
const CONNECTION_STRING = "mongodb://localhost:27017/test";
// 반복 처리를 이용한 시퀀스 발행
var insertUser = function (userinfo, callback) {
MongoClient.connect(CONNECTION_STRING).then((db) => {
// 반복 처리
var loop = function () {
db.collection("users")
.find({}, { _id: 0, userid: 1 })
.sort({ userid: -1 })
.limit(1)
.toArray((err, docs) => {
if (err) {
callback && callback(err, null);
return;
}
// 시퀀스 생성
var seq = docs.length > 0 ? docs[0].userid + 1 : 0;
// 시퀀스 설정
userinfo.userid = seq;
// 도큐먼트 등록
db.collection("users").insertOne(userinfo, (err, res) => {
// 시퀀스 번호가 사용되는 경우 재귀 실행
if (err && err.code === 11000) {
loop();
return;
}
callback && callback(err, res);
});
});
};
// 반복 처리의 최초 실행
loop();
});
};
// 실제로 등록하기
insertUser({
name: "kimkc"
});
insertUser({
name: "devkuma"
});
사용
> node ./index.js
결과
> db.users.find({}, { _id: 0 })
{ "name" : "kimkc", "userid" : 0 }
{ "name" : "devkuma", "userid" : 1 }
참고 문서
최종 수정 : 2022-01-13