요즘 면접 보느라 매일매일 쏘다니는 중인데
👨 : 님? MongoDB 써봄?
👽 : 아.. 아뇨..!
👨 : (왜 왔냐는 듯이) ? 아 그러시면 mongoDB 관련 질문은 안하고...
후... 또 나의 빈부분이 꿰뚫리는 것 같았다.
그럼 간단하게 CRUD 정도만 해볼까? 하며 여러 블로그를 탐색하기 시작했다.
Gopher였던 내게 가장 도움이 됐던 것은 2번, 몽고+고랭으로 CRUD 구현하기 였다. 물론 특정 언어를 너무 사랑하지 말라던 그.. 유명하신 분의 말이 있긴 하지만, 학부때 C++좀 했고.. 보안 하면서 Python도 좀 했으니.. 지금은 Go를 조금 사랑해도 되지 않을까요 선생님? (근데 왜 이렇게 Java는 정이 안들까)
각설하고, MongoDB 설치부터 간단한 쿼리 정도를 다뤄보겠다.
는 그냥 홈페이지에서 받으세요. 설치 짱쉬움 다운로드 링크
근데 다 비교하면 너무 오래걸리니까 짧게 비교함. 30초도 안걸림.
RDBMS랑 MongDB는 명칭이랑 형태가 조금 다름.
NoSQL은 대개 Key/Value 형식의 구조를 가짐. 생긴거 보자마자 JSON 생각나야함.
MongoDB도 전통적인 NoSQL이라서 Key/Value 형식의 데이터 집합임.
위에서 말하는 Document라는게 결국 {}중괄호로 둘러싸인 하나의 Key/Value인거임.
오 구조체처럼 생겼네
RDBMS에서 Table은 가로(라벨) 세로(속성)을 이용한 데이터 집합을 가짐.
근데 MongoDB는 그런거 없이, Key/Field 형식의 데이터 형식을 모아 하나의 Document가 됨. Document가 여러개 모이면 Collection이라고 함.
형태는 다른데 장단점이 있나?
어차피 MongoDB 글이니까 MongoDB 장단점만 보면,
RDBMS도 수평확장 가능한데 태생이 수평 확장을 지원하기 위해 만든 애들이 아니라서 좀 더 불편하다고 함. 근데 이미 30초도 지났고, 이런거 다 따지다간 데이터 저장하고 불러오는 정도로 끝내려던 글이 너무 길어질 것 같아서 여기서 뚝 끊겠음.
이 분 블로그에 글 잘 나와있음. 나머지는 여기서 보셈 (https://kciter.so/posts/about-mongodb)
우선 DB부터 연결해야된다. MongoDB의 기본 포트는 27017이므로, 아래와 같이 입력하여 연결해준다.
func ConnectDB() (client *mongo.Client, err error) { clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") client, err = mongo.Connect(context.TODO(), clientOptions) if err != nil { return nil, err } err = client.Ping(context.TODO(), nil) if err != nil { return nil, err } return }
나중엔 auth를 위해 mongo server에 id, pw도 만들어줘야 하지만 지금은 안했다.
아까 Key/Value 형태로 저장해야된다고 언급했다.
그리고 구조체 처럼 생겼다는 말도 살짝 흘렸다.
이를 통해 struct를 만들고 Field만 잘 맞춰준다면 Json 패키지로 마샬, 언마샬, 인코딩, 디코딩이 가능하지 않을까? 라는 생각이 들어야 된다.
맞음. 잘 된다.
{ uuid:"dbslqjtjfdbslzmdkdlepsxlvlzpdltusdlfksmsdltkdgksanswkduf" name:"damon" age:100 address:"서울 어딘가" }
이렇게 생긴 json 파일이 있다고 하자.
이걸 Decoding하려면 아래와 같은 구조체를 만들어주면 된다.
type User struct{ UUID string `json:"uuid"` Name string `json:"name"` Age int64 `json:"age"` Address string `json:"address"` }
어쨌든 저 json 파일을 mongodb에 저장하려고한다면!
func Write(writeDB *mongo.Collection, docs User) { // 대충 공공api 비스무리한거로 json파일 받아왔다는 가정 하에 err = json.NewDecoder(resp.Body).Decode(docs) num, err := writeDB.CountDocuments(nil, bson.M{"uuid": docs[i].uuid}) if num > 0 { continue } _, err = writeDB.InsertOne(context.TODO(), docs[i]) if err != nil { return } }
Write 쉽죠? 데이터 꺼내 쓸 때도 짱 쉽다.
func Load(col *mongo.Collection, page int64) (docs []User) { findOptions := options.Find() findOptions.SetSort(bson.D{{"created_at", -1}}) findOptions.SetLimit(20) findOptions.SetSkip((page - 1) * 20) res, err := col.Find(context.Background(), bson.D{}, findOptions) if err != nil { return } err = res.All(nil, &docs) if err != nil { return } return docs }
그냥 꺼내기만 하면 좀 그러니까 옵션을 줘봤다.
그리고 실제 찾을 때는
위와 같이 찾을 수 있었다. 솔직히 mongodb 처음 배우는 사람도 이정도는 30분이면 코딩할 수 있을거라 생각한다.
근데 왜 나는 과제 낼 때 skip 옵션 안쓰고 모든 데이터를 다 구조체로 디코딩한 다음 인덱싱했을까? 내자마자 30분이따가 바로 생각나는건 왜일까?
매일 매일 이불킥 할 거리 만들어내는 난 진짜 레전드다...