Seize the day

POST : Backend study

Mongodb 내장 함수 study

Mongo에 내장 함수를 만들 수 있다고해서 테스트 해 봤다. mongo 쉘에서 테스트해보니 잘 된다.  아마도 nodejs에서는 이 js function을 호출할 수 있는 라이브러리가 있을 것  같다. deno에 mongodb 라이브러리인 https://deno.land/x/mongo  에서는 아직 호출 기능을 제공하지 않는다. mongodb는 trigger도 단독 서버에서는 지원하지 않는다. 관계형 db에서는 trigger를 유용하게 사용했었는데 아쉽다.

 

getNextTS 는 moneyBookId를 별로 sequence 를 증가시켜서 리턴하는 함수다. 

> db.MoneyBook.insertOne({name:"Money book1"})
{
	"acknowledged" : true,
	"insertedId" : ObjectId("610654e943cca4c015817161")
}

> db.MoneyBook.find()
{ "_id" : ObjectId("610654e943cca4c015817161"), "name" : "Money book1" }
> db.TSList.insertOne({moneyBookId: ObjectId("610654e943cca4c015817161"), collectionName: "transfer", ts: 1})
{
	"acknowledged" : true,
	"insertedId" : ObjectId("6106555d43cca4c015817162")
}

> db.TSList.find()
{ "_id" : ObjectId("6106555d43cca4c015817162"), "moneyBookId" : ObjectId("610654e943cca4c015817161"), "collectionName" : "transfer", "ts" : 1 }

# 함수 저장
db.system.js.remove({_id: 'getNextTS'})
db.system.js.insertOne(
    {
        _id : 'getNextTS',
        value : function(moneyBookId, collectionName) {
            var ret = db.TSList.findAndModify( { query: {moneyBookId: moneyBookId, collectionName: collectionName}, update: {$inc: {ts: 1} }, new: true } );
            return ret.ts;
        }
    }
)
> db.loadServerScripts()
> getNextTS(ObjectId("610654e943cca4c015817161"), "transfer")
4

 

Client 앱의 관계형  db의 id는 integer형으로 AUTOINCREMENT 를 이용하면 손쉽게 사용할 수 있다. Mongodb의 id는 이런 형태가 아니기 때문에 코드 구현으로 생성해 주는 방법이 필요하다.  client에도 server id를 저장할 필요가 있어서, type을 Int로 맞출필요가 있다. 

// collectin name
export const kNextId = "next_id"

// id auto increment
export interface INextId {
    did: number
    cid: number,
    id: number
}
import { Bson, MongoClient } from "https://deno.land/x/mongo/mod.ts"

class MyMongoClient {
    dbName: string
    url: string
    client: MongoClient
    
    constructor(dbName: string, url: string) {
        this.dbName = dbName;
        this.url = url;
        this.client = {} as MongoClient;
    }

    async connect() {
        console.log("mongodb connecting ...")
        const client = new MongoClient();
        await client.connect(this.url);
        this.client = client;
        console.log("mongodb connected OK")
    }
    
    getDatabase() {
        return this.client.database(this.dbName);
    }
}


export const mongoClient = new MyMongoClient("testdb", "mongodb://127.0.0.1:27017")
await mongoClient.connect()

const db = mongoClient.getDatabase()
const nextIdCollection = db.collection<INextId>(kNextId)
export async function getNextId(cid: number, did: number) : Promise<INextId | undefined> {
    return await nextIdCollection.findAndModify(
        {cid: cid, did: did},
        { 
          update: { $inc: { id: 1 } },
          new: true, 
          upsert: true 
        }
    )
}

 

이렇게 사용한다. 서버에는 사용자 별로 did가 생성되는데, 특정 collection에  특정  did 별로 sequence를 발급하는 함수를 직접 호출해서 구하고, insert 하기 전에 그 값을 사용하도록 한다. 

const aid = (await getNextId(kCidAccount, did))!.id

 

top

posted at

2021. 8. 1. 17:42


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크