태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

'MongoDB'에 해당되는 글 2건

  1. 2012.08.02 도깨비: 요청/응답 json 포맷 사용 + mongodb 저장소 붙이기 (6)
  2. 2012.07.26 MongoDB 읽고쓰기 (6)

도깨비: 요청/응답 json 포맷 사용 + mongodb 저장소 붙이기

Daily life/Hard study 2012. 8. 2. 22:20

지난번에 작업 - http://blog.dgoon.net/449 - 하다 말았던 부분을 이어서 한다. 도깨비에 추가로 할 작업은 다음 두가지이다.

1. 일단 요청/응답 포맷을 json으로 바꾼다.
2. persistent layer를 붙인다(mongodb?)

-----
query string 이나 parameter 는 버린다.
POST 로 요청을 받고 -> Content-type 이 application/json 인지 확인하고 -> body 를 읽어서 json.loads 를 한다.
요청이 가져야 하는 값들은 여기서 나오는 json 에 모두 포함되어 있어야 한다. 몇 가지 사소한 것들을 적어둔다.

a. 요청 타입(POST/GET)은 지난번에 @require_http_methods("POST") 로 강제했다
b. content-type은 request.META.get('CONTENT-TYPE') 에 들어있다.
c. body는 request.read() 를 하면 나온다

필수 데이터가 들어있는지 확인하는 코드(check_required)와 content-type을 확인하는 코드(check-content-type)을 함수로 분리하면 더미 로직은 get/put 둘 모두,

        check_content_type(request, "application/json")
        body = request.read()
        req_dict = simplejson.loads(body)
        check_required(GET_REQUIRED_FIELDS, req_dict.keys())
        print req_dict


이 정도로 간단해진다. 조건이 맞지 않는 경우 check_required, check_content_type 함수들은 직접 예외를 생성해서 던진다. 테스트 요청을 날리던 get.py, put.py 에서는 content-type 만 application/json 으로 바꾸고, urlencode 하던 부분을 simplejson.dumps 로만 바꾸면 된다.

{'app_key': 'deadbeef', 'condition': {}}
[02/Aug/2012 21:06:05] "POST /api/v1/get/ HTTP/1.1" 200 2
{'content': 'THIS_IS_CONTENT', 'tag_list': ['tag1', 'tag2', 'tag3'], 'meta': {}, 'app_key': 'deadbeef'}
[02/Aug/2012 21:06:16] "POST /api/v1/put/ HTTP/1.1" 200 2

이전보다 코드도 짧아지고, tag_list 도 리스트로 제대로 들어온다. 에잉 훨 낫네.

-----
persistent layer를 붙인다. 전에 튜토리얼을 따라가본 몽고디비를 쓰고 싶다. 그때는 c++ 클라이언트였는데, 파이썬이라고 뭐 딱히 다르진 않지 싶다. 더 쉽겠지...

http://www.mongodb.org/display/DOCS/Drivers -> http://www.mongodb.org/display/DOCS/Python+Language+Center

여기서 찾아보면 몇 가지 라이브러리가 있다. PyMongo 를 선택. 일단 언제나처럼 pip,easy_install,apt-get 순서로 패키지가 있나 뒤져본다.

sudo pip install pymongo

빙고. 파이썬 쉘 띄워서 import pymongo 해보니 뭔가 임포트 된다. 이걸 쓰면 되겠다.

http://api.mongodb.org/python/current/tutorial.html

여기 튜토리얼이니 잠깐 읽어보면 어렵지 않아요~ 지난번에 삽질하면서 katy 에 몽고디비 설치는 해 두었으니 그대로 활용하자. db=tokebi, collection=twit 으로 간다. store_mongodb.py 를 만들고, MongoStore 클래스에 몽고디비 접근 구현 코드를 둔다. 인터페이스는 mongo_store.get/put 이며 api_get, api_put 이 받은 요청을 거의 그대로 받는다.


api_get:
        app_key, condition = get_items(req_dict, GET_REQUIRED_FIELDS)             
        store = MongoStore('twit')
        retrieved = store.get(app_key, condition)

api_put:
        app_key, content, tag_list, meta = get_items(req_dict, PUT_REQUIRED_FIELDS)
        store = MongoStore('twit')
        ack = store.put(app_key, content, tag_list, meta)

api_get, api_put 에 각각 위의 코드가 추가되었다. 테스트 요청을 날려보면서 디버깅을 좀 해야 했는데, python get.py localhost 2223 > ~/public_html/get_error.html 등으로 저장한 뒤에 브라우저로 열어보면 좀 쉽다. 몽고디비에 쓰고 읽을 때 필요한 자료구조는 뭘까 하고 튜토리얼을 봤더니,

In PyMongo we use dictionaries to represent documents. ...

저장 단위가 파이썬 맵이므로 구현은 아주 간단하다. 심지어 문서를 꺼내오는 조건도 사전이므로,몽고디비 접근은 거의 자명하다.

#-*- encoding: utf-8 -*-from pymongo import Connection
CONN = Connection()

def doc2dict(d):
    ret = dict(d)
    ret['_id'] = str(ret['_id'])
    return ret

class MongoStore(object):
    def __init__(self, collection):
        self.collection = CONN.tokebi[collection]

    def get(self, app_key, condition):
        cond = condition.copy()
        cond['app_key'] = app_key
        return map(doc2dict, self.collection.find(condition))

    def put(self, app_key, content, tag_list, meta):
        doc = {
            'app_key': app_key,
            'content': content,
            'tag_list': tag_list,
            'meta': meta,
        }
        return self.collection.insert(doc)


api_get, api_put 에서 응답을 적절히 json 포맷으로 만들어 준다면 테스트 요청을 날리는 get.py 에서는 여러개의 문서 리스트를 응답으로 얻게 된다. 받은 결과를 화면에 찍어보면,

dgoon@katy:~/works/tokebi/sample_query$ python get.py localhost 2223
{'Content-type': 'application/json', 'Accept': 'text/plain'}
{'condition': {}, 'app_key': 'deadbeef'}
0
        content THIS_IS_CONTENT
        _id 501a74c272653e2217c9b255
        meta {}
        app_key deadbeef
        tag_list ['tag1', 'tag2', 'tag3']
1
        content THIS_IS_CONTENT
        _id 501a74d472653e222068f2b8
        meta {}
        app_key deadbeef
        tag_list ['tag1', 'tag2', 'tag3']
2
        content 두만강푸른물에
        _id 501a750372653e222068f2b9
        meta {}
        app_key deadbeef
        tag_list [u'\uac15\uc0b0\uc5d0', u'\ub178\ub798']
3
        content 티비유치원 하나둘셋
        _id 501a768072653e225e6cb3c1
        meta {}
        app_key deadbeef
        tag_list ['hana', 'dul', 'set']


이렇게 확인할 수 있다. 한글도 잘 들어가는 것을 확인할 수 있다. 2번 문서의 tag_list에 들어있는 것은,

>>> for k in [u'\uac15\uc0b0\uc5d0', u'\ub178\ub798']:
...     print k
...
강산에
노래

이렇게 유효한 한글이다. PyMongo 튜토리얼에서 설명되어 있는데 - BSON strings are UTF-8 encoded 라고 한다. Unicode문자열은 encode 되어 저장된다고. 그리고 simplejson 으로 직렬화 할때는 다시 유니코드가 되어서 응답을 받은 쪽에서는 한글이 모두 유니코드로 떨어지게 된다. 나중에 좀 헷갈릴 것 같다.


-> http://git.dgoon.net/?p=tokebi.git;a=commit;h=da49398646c0812a0d33d71cbec23e5052f5ca09


-----

추가적으로 해야 하는 작업은 ... 잊고 있었는데, 나 말고 다른 사람도 이걸 쓰게 하려면


1. user_id 같은걸 넣어야 하고,


최신 엔트리를 가져오려면,


2. created_at 이 필요하고,


사람을 가리거나 정렬이 필요하니


3. 적절한 인덱스 가 필요하다.


다음 작업은 이상 3개가 되겠다.

Trackbacks 0 : Comments 6
  1. Favicon of http://ub.cheapshoesel.com/ nike shoes 2013.04.08 05:44 Modify/Delete Reply

    우리가 어디에 있는가가 중요한 것이 아니라 어디로 가야 하느냐가 중요한것이다

  2. Favicon of http://ntu.contact-hotel.com/longchamp.php sac longchamp 2013.04.13 20:52 Modify/Delete Reply

    매우 지원, 아주 좋아, http://ntu.4dmv.com/montblanc.php mont blanc pens.

  3. Favicon of http://www.todsoutletonlinexx.com/ tods shoes 2013.04.23 18:22 Modify/Delete Reply

    당신은 내가사랑할 만한 사람이 아니예요,사랑하지 않으면 안될 사람이예요.

  4. Favicon of http://frk.hairstraightenernx.com ghd straightener 2013.04.29 03:30 Modify/Delete Reply

    좋으면 좋고 싫으면 싫은 거지, 뭐가 이렇게 어렵고 복잡하냐구

  5. Favicon of http://frk.shoesxstorex.com/ jordan 18 2013.04.29 08:16 Modify/Delete Reply

    좋으면 좋고 싫으면 싫은 거지, 뭐가 이렇게 어렵고 복잡하냐구

  6. Favicon of http://2962sacresgion511.com/ChicagoBlackhawksjersey.php Chicago Blackhawks Jersey 2013.07.15 18:36 Modify/Delete Reply

    태양이 바다에 미광을 비추면,나는 너를 생각한다.

Write a comment


MongoDB 읽고쓰기

Daily life/Hard study 2012. 7. 26. 23:10

몽고DB의 C++ 클라이언트는 github 에서 구할 수 있다.

mongodb c++ client: github.com/mongodb/mongo
mongodb 서버는 빌드해서 설치할 수도 있지만 귀찮으니, apt-get 으로 설치하기로 한다.

a. debian: mongodb-server mongodb-dev mongodb-clients mongodb
b. ubuntu: mongodb
c. etc: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-debian-or-ubuntu-linux/

세번째가 제일 나은 듯 하다. 그 와중에 upstart 라는걸 보게 되었다. 나중에 천천히 읽어볼 것: http://upstart.ubuntu.com/
사용한 client 라이브러리는 C++ 2.1.2 이다. API DOC: http://api.mongodb.org/cplusplus/2.1.0/


0. Install
  mongodb server:
  sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
  echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" >> /etc/apt/sources.list
  sudo apt-get update
  sudo apt-get install mongodb-10gen


  mongodb client library:
  wget http://downloads.mongodb.org/cxx-driver/mongodb-linux-x86_64-2.1.2.tgz
  tar zxvf mongodb-linux-x86_64-2.1.2.tgz
  cd mongo-cxx-driver-nightly
  sudo scons install

이렇게 하면 /usr/local 밑에 몽고DB 클라이언트 라이브러리가 설치된다.
/usr/local/include/mongo 아래쪽 권한이 좀 이상하게 설치되어서 sudo chmod 755 /usr/local/include/mongo -R 을 해 주었다.
언제나 그런건지, scons 사용을 잘못한건지는 잘 모르겠다.

C++ 튜토리얼은 이걸 보면 된다. http://www.mongodb.org/pages/viewpage.action?pageId=133415
이 아래의 내용은 기본적으로 튜토리얼 내용을 그냥 따라간 로그이다.

1. Connect
#include <cstdio>
#include "client/dbclient.h"
using namespace std;

int main() {
    try {
        mongo::DBClientConnection c;
        c.connect("localhost");
    }
    catch (mongo::DBException& e) {
        printf("Error: %s\n", e.what());
    }
    return 0;
}


g++ -I/usr/local/include/mongo test.cpp -lboost_system -lboost_thread -lboost_filesystem -lmongoclient -o test

이렇게 빌드하면 ./test 를 실행했을때 아무일도 안 일어나게 된다. localhost 를 remotehost 같은걸로 바꾸고 해보면 에러가 나는걸 확인할 수 있다.


$ ./test
Thu Jul 26 21:36:19 getaddrinfo("remotehost") failed: No address associated with hostname
Error: can't connect couldn't connect to server remotehost:27017

2. Insert
접속은 했으니 이제 읽기/쓰기를 해보자. 아직 아무것도 들어있는게 없으므로, 먼저 쓰기를 하고 나서 쓴 값을 읽어보도록 하자. 몽고DB는 데이터를 BSON이라는 형식으로 저장하는데, JSON이랑 닮은 - 정확히는 json with custom extension - 포맷이다. 방법은 간단하다. BSON 객체를 생성 -> DB에 추가, 하면 된다.

a. BSON 객체 생성
BSON 객체는 BSONObjBuilder 를 사용해서 만든다. 사용법은 아래와 같다.

BSONObjBuilder builder;
builder.append("HERE_GOES_KEY", "HERE_GOES_VALUE");
builder.append("name", "dgoon");
BSONObj obj = builder.obj();

이걸 아래와 같이 체이닝 할 수도 있다

BSONObj obj = BSONObjBuilder().append("HERE_GOES_KEY", "HERE_GOES_VALUE").append("name", "dgoon").obj();

하지만 난 여러 줄에 풀어 쓰는걸 선호한다.
그 외에 stream 체이닝이나, Object ID 를 명시적으로 지정하는 방법 등 몇 가지 화두가 더 있지만 과감하게 생략.

b. DB 에 추가
이렇게 만든 BSONObj 객체를 DB에 넣기 위해서는,

conn.insert("database.collection", obj);

를 해주면 된다. database, collection 은 무엇인가! 대충 RDB 개념을 빌리자면 database=database, collection=table 정도로 생각하면 된다.

#include <cstdio>
#include "client/dbclient.h"
using namespace std;

int main() {
    try {
        mongo::DBClientConnection c;
        c.connect("localhost");

        mongo::BSONObjBuilder b;
        b.append("name","dgoon");
        b.append("addr", "nakseongdae");
        mongo::BSONObj p=b.obj();

        c.insert("mydb.character", p);
    }
    catch (mongo::DBException& e) {
        printf("Error: %s\n", e.what());
    }
    return 0;
}


소스코드를 이렇게 수정하고 나서 실행해보면, 역시 아무런 말도 없다. 잘 된거겠지… 확인을 해보자. 읽는 코드를 만들기 전에 잠깐 shell 에서 보도록 한다.

c. SHELL

몽고DB는 강력한지는 잘 모르겠고, 여튼 쉘 환경이 있다. 위의 c로 설치했다면 mongo 라는 커맨드가 있을 것이다.

dgoon@katy:~/works/mongo-cxx-driver-nightly$ mongo
MongoDB shell version: 2.0.6
connecting to: test
>

위에서 mydb.character 에 데이터를 넣었던 것이 기억나는가? db=mydb, collection=character 이다.

> show dbs
local     (empty)
mydb     0.078125GB
> use mydb
switched to db mydb
> show collections
character
coll
system.indexes
things
> db
mydb
> db.character
mydb.character
> db.character.find()
{ "_id" : ObjectId("50113dbb9aa68f690df58a39"), "name" : "dgoon", "addr" : "nakseongdae" }
{ "_id" : ObjectId("50113dbe9aa68f690df58a3a"), "name" : "dgoon", "addr" : "nakseongdae" }
{ "_id" : ObjectId("50113dbf9aa68f690df58a3b"), "name" : "dgoon", "addr" : "nakseongdae" }
>

이렇게 들어가 있다. … 왜 3개냐구? 내가 실행을 3번 했으니까. … 그렇다, 딱히 KEY 를 지정해 준 것이 아니기 때문에 여러번 추가해도 중복이 아니므로, 실행한 횟수만큼 여러개가 들어간다.


3. Retrieve

읽어오는건 코드가 조금 더 길다. 읽어올 조건과 함께 query를 날린다 -> 커서를 받는다 -> 커서를 순회하며 데이터를 꺼낸다, 순서로 작업하면 된다.

데이터를 꺼내오기 위해 명시해 주어야 하는 것은, 어디에서? 어떤 녀석을? 이다. connection.query 는 2개의 인자를 받는데, 하나는 어디에서? 또 하나는 어떤 녀석을? 에 대한 것이다. 여기서 조건 역시 BSONObj 타입으로 들어간다. 그냥 빈 객체를 넣으면 모두 다 꺼내오라는 뜻이다. BSONObj 객체의 각 필드가 AND로 조합되어 조건으로 들어간다고 한다. 우리는 모두다 꺼내와보자.

test.cpp 는 이제 아래와 같이 길어졌다.

#include <cstdio>
#include "client/dbclient.h"
using namespace std;

int main() {
    try {
        mongo::DBClientConnection c;
        c.connect("localhost");

        mongo::BSONObjBuilder b;
        b.append("name","dgoon");
        b.append("addr", "nakseongdae");
        mongo::BSONObj p=b.obj();

        c.insert("mydb.character", p);

        auto cursor=c.query("mydb.character",
                            mongo::BSONObj());
        while (cursor->more()) {
            printf("%s\n", cursor->next().toString().c_str());
        }
    }
    catch (mongo::DBException& e) {
        printf("Error: %s\n", e.what());
    }
    return 0;
}


auto는 타이핑을 줄이기 위해 사용했는데, 정확한 타입은 auto_ptr<mongo::DBClientCursor> 이다. auto_ptr을 사용한 이유는 소유권을 넘기면서 객체 소멸을 라이브러리 사용자(caller)에게 넘기고 난 귀찮으니 잊어버리겠어 -_- 라는 것이라 생각한다. auto 사용때문에 아래 컴파일 옵션에 -std=c++0x 가 추가된 것에 주의하자.

dgoon@katy:~/works/mongo-cxx-driver-nightly$ g++ -I/usr/local/include/mongo test.cpp -lboost_system -lboost_thread -lboost_filesystem -lmongoclient -std=c++0x -o test
goon@katy:~/works/mongo-cxx-driver-nightly$ ./test
{ _id: ObjectId('50113dbb9aa68f690df58a39'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbe9aa68f690df58a3a'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbf9aa68f690df58a3b'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140789aa68f690df58a3c'), name: "dgoon", addr: "nakseongdae" }
goon@katy:~/works/mongo-cxx-driver-nightly$ ./test
{ _id: ObjectId('50113dbb9aa68f690df58a39'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbe9aa68f690df58a3a'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbf9aa68f690df58a3b'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140789aa68f690df58a3c'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140799aa68f690df58a3d'), name: "dgoon", addr: "nakseongdae" }
goon@katy:~/works/mongo-cxx-driver-nightly$ ./test
{ _id: ObjectId('50113dbb9aa68f690df58a39'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbe9aa68f690df58a3a'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbf9aa68f690df58a3b'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140789aa68f690df58a3c'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140799aa68f690df58a3d'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407a9aa68f690df58a3e'), name: "dgoon", addr: "nakseongdae" }
goon@katy:~/works/mongo-cxx-driver-nightly$ ./test
{ _id: ObjectId('50113dbb9aa68f690df58a39'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbe9aa68f690df58a3a'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbf9aa68f690df58a3b'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140789aa68f690df58a3c'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140799aa68f690df58a3d'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407a9aa68f690df58a3e'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407b9aa68f690df58a3f'), name: "dgoon", addr: "nakseongdae" }
goon@katy:~/works/mongo-cxx-driver-nightly$

실행할 때마다 엔트리가 하나씩 늘어나면서 가져오는 갯수도 늘어나고 있다. 참고로 b.append("age", 18); 처럼 value 에는 문자열 이외의 타입도 들어갈 수 있다.


4. Update

데이터를 가져오는 것과 별로 다르지 않다. 어디에 있는? 어떤 아이들에? 어떤 값을? 을 지정해주면 된다.


#include <cstdio>
#include "client/dbclient.h"
using namespace std;

int main() {
    try {
        mongo::DBClientConnection c;
        c.connect("localhost");

        c.update("mydb.character", // 어디에 있는?
                 BSON("age" << 18),  // 어떤 아이들에게?
                 BSON("$inc" << BSON("visits" << 1)));  // 어떤 값을??

        auto cursor=c.query("mydb.character",
                            mongo::BSONObj());
        while (cursor->more()) {
            printf("%s\n", cursor->next().toString().c_str());
        }
    }
    catch (mongo::DBException& e) {
        printf("Error: %s\n", e.what());
    }
    return 0;
}

이렇게 하면 mydb.character 에서 age=18 인 아이들을 찾아서(설명엔 없지만 위에서 몇개 추가해 두었다) visits 을 1 증가시킨다고 한다. $inc 가 뭔가 특별한 의미가 있나보다. 그래서 위의 프로그램을 여러번 실행하면,

dgoon@katy:~/works/mongo-cxx-driver-nightly$ ./test
{ _id: ObjectId('50113dbb9aa68f690df58a39'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbe9aa68f690df58a3a'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbf9aa68f690df58a3b'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140789aa68f690df58a3c'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140799aa68f690df58a3d'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407a9aa68f690df58a3e'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407b9aa68f690df58a3f'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011421d9aa68f690df58a40'), addr: "nakseongdae", age: 18, name: "dgoon", visits: 10 }
{ _id: ObjectId('5011421f9aa68f690df58a41'), addr: "nakseongdae", age: 18, name: "dgoon", visits: 1 }
dgoon@katy:~/works/mongo-cxx-driver-nightly$ ./test
{ _id: ObjectId('50113dbb9aa68f690df58a39'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbe9aa68f690df58a3a'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('50113dbf9aa68f690df58a3b'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140789aa68f690df58a3c'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('501140799aa68f690df58a3d'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407a9aa68f690df58a3e'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011407b9aa68f690df58a3f'), name: "dgoon", addr: "nakseongdae" }
{ _id: ObjectId('5011421d9aa68f690df58a40'), addr: "nakseongdae", age: 18, name: "dgoon", visits: 11 }
{ _id: ObjectId('5011421f9aa68f690df58a41'), addr: "nakseongdae", age: 18, name: "dgoon", visits: 1 }

이런 결과가 나온다. 처음 한 번은 5011421f9aa68f690df58a41 를 고치더니 그 후로는 5011421d9aa68f690df58a40 를 고치고 있다. 어어?
… 요약하면 해당 조건에 맞는 데이터가 여러개 있는 경우에, 그 중 임의로 하나를 선택하여 갱신, 한다고 생각한다.
혹은 선택 기준은 있지만, 갱신할 때마다 선택되는 아이들이 달라지게 될 수도 있다. 여튼 곤란.

uniqueness 를 보장하기 위해서는 매번 업데이트 할 때마다 query를 보내어 확인을 한번 해 주어야 하는건가?

조건에 맞는 엔트리가 하나도 없는 경우는 아무일도 일어나지 않는다.



+
http://api.mongodb.org/cplusplus/2.1.0/dbclient_8h_source.html


ensureIndex의 함수 시그니쳐는 다음과 같다. unique=false가 기본값인데, true를 줄 수 있다.


virtual bool ensureIndex( const string &ns , BSONObj keys , bool unique = false, const string &name = "", bool cache = true, bool background = false, int v = -1 );


주의할 점은 특정 key에 unique=true가 걸리면 그 키가 동일한 경우는 물론 이고, 해당 키가 "없는 것도 하나의 값" 이 되어 버린다. 즉 ensureIndex("mydb.character", fromjson("{age:1}"), true); 로 인덱스를 생성했다면

mydb.character 에 age 가 없는 데이터는 단 하나밖에 존재할 수 없다

는 사실.


+ 도깨비의 백엔드 저장소로 몽고디비 사용할 예정.


Trackbacks 0 : Comments 6
  1. zzugg 2012.07.27 02:07 Modify/Delete Reply

    c++ client에는 sparse 옵션이 없나보네요?

  2. Favicon of http://blog.shurain.net 슈레인 2012.07.27 02:19 Modify/Delete Reply

    Mongo DB is Web Scale. http://youtu.be/b2F-DItXtZs

  3. Favicon of http://9901ccgenevois.com/clfrance.php christian louboutin 2013.07.14 09:05 Modify/Delete Reply

    당신은 내가사랑할 만한 사람이 아니예요,사랑하지 않으면 안될 사람이예요.

  4. Favicon of http://18028hiphopweekly.com/mag/thankhot.php nike shoes 2013.07.14 20:33 Modify/Delete Reply

    당신 매력있어, 자기가 얼마나 매력있는지 모르는게 당신매력이야

Write a comment