12-18 14:29
Notice
Recent Posts
Recent Comments
관리 메뉴

Scientific Computing & Data Science

[MongoDB] Update Modifiers / Part 9. - findAndModify 본문

Data Science/MongoDB

[MongoDB] Update Modifiers / Part 9. - findAndModify

cinema4dr12 2014. 1. 31. 08:32

by Geol Choi | 

이번 글에서는 findAndModify를 통해 도큐먼트를 업데이트하는 방법에 대해 알아보겠다.
findAndModify는 제시된 기준의 아이템을 찾고 업데이트하는 일련의 과정을 한 번에 처리할 수 있는 편리한 명령이다.
findAndModify 명령어의 인자에는 sort 기능이 있는데 지금까지 다룬 적이 없으므로 이 부분을 우선 이해하고 넘어가도록 하겠다.

다음과 같이 데이터를 준비하자.

db.tasks.insert({todo : "shopping", status : "READY", priority : "4"})
db.tasks.insert({todo : "studying Mongo DB", status : "READY", priority : "1"})
db.tasks.insert({todo : "reporting the current job", status : "DONE", priority : "8"})
db.tasks.insert({todo : "cleaning my room", status : "READY", priority : "3"})
db.tasks.insert({todo : "meeting friends", status : "DONE", priority : "7"})
db.tasks.insert({todo : "depositing money", status : "RUNNING", priority : "6"})
db.tasks.insert({todo : "take a walk", status : "RUNNING", priority : "5"})
db.tasks.insert({todo : "sending an email", status : "READY", priority : "2"})

"todo"는 "해야 할 일"이며, "status"는 진행상태이며 "REDAY(준비)", "(처리 중)", "DONE(처리완료)"로 구분된다. "priority"는 "우선순위"이며 값이 클수록 높은 우선순위를 의미한다.
그럼 "status"가 "REDAY"인 것 중에 우선순위가 높은 순서대로 정렬(sort)해 보기 위해 다음과 같이 테스트 해 본다.

> db.tasks.find({status : "READY"}).sort({priority : -1})
{ "_id" : ObjectId("52eba10e5e3b86c2a732508c"), "todo" : "shopping", "status" : "READY", "priority" : "4" }
{ "_id" : ObjectId("52eba10e5e3b86c2a732508f"), "todo" : "cleaning my room", "status" : "READY", "priority" : "3" }
{ "_id" : ObjectId("52eba10e5e3b86c2a7325093"), "todo" : "sending an email", "status" : "READY", "priority" : "2" }
{ "_id" : ObjectId("52eba10e5e3b86c2a732508d"), "todo" : "studying Mongo DB", "status" : "READY", "priority" : "1" }

"priority"가 -1인 것은 값을 높은 순서대로 정렬하며, 만약 1인 경우 반대로 낮은 순서로 정렬된다.(직접 테스트 해 보시기 바란다)
이제 본격적으로 findAndModify를 이해해 보자. "status"가 "REDAY"인 것들 중에서 "priority"가 가장 높은 것을 찾아 "status"를 "RUNNING"으로 바꾸는 명령을 수행한다.

다음 명령을 입력해 보자.

db.tasks.findAndModify({
	query : {status : "READY"},
	sort : {priority : -1},
	update : {"$set" : {status : "RUNNING"}}
})

위의 명령에서 "query"는 업데이트할 선택 기준을, "sort"는 정렬의 기준을, "update"는 선택된 도큐먼트를 업데이트 할 내용을 입력한다. 이외에 findAndModify의 입력 파라미터들에 대해서는 뒷부분에서 좀 더 자세히 설명하기로 한다.

수행한 명령에 대한 결과를 살펴보면,

> db.tasks.find()
{ "_id" : ObjectId("52eba10e5e3b86c2a732508c"), "priority" : "4", "status" : "RUNNING", "todo" : "shopping" }
{ "_id" : ObjectId("52eba10e5e3b86c2a732508d"), "todo" : "studying Mongo DB", "status" : "READY", "priority" : "1" }
{ "_id" : ObjectId("52eba10e5e3b86c2a732508e"), "todo" : "reporting the current job", "status" : "DONE", "priority" : "8" }
{ "_id" : ObjectId("52eba10e5e3b86c2a732508f"), "todo" : "cleaning my room", "status" : "READY", "priority" : "3" }
{ "_id" : ObjectId("52eba10e5e3b86c2a7325090"), "todo" : "meeting friends", "status" : "DONE", "priority" : "7" }
{ "_id" : ObjectId("52eba10e5e3b86c2a7325091"), "todo" : "depositing money", "status" : "RUNNING", "priority" : "6" }
{ "_id" : ObjectId("52eba10e5e3b86c2a7325092"), "todo" : "take a walk", "status" : "RUNNING", "priority" : "5" }
{ "_id" : ObjectId("52eba10e5e3b86c2a7325093"), "todo" : "sending an email", "status" : "READY", "priority" : "2" }

예상대로 "status"가 "READY"였던 것 중 가장 우선순위가 높았던 "shopping"의 "status"가 "RUNNING"으로 바뀌었음을 확인할 수 있다.

이 명령을 반복적으로 수행하면 우선순위가 높은 순서대로 "RUNNING"으로 바뀌는 것을 확인할 수 있을 것이다. 만약 더 이상 업데이트 할 것이 없으면 "null"을 반환한다.

findAndModify의  주요 입력 파라미터를 정리해 보자. (보다 자세한 파라미터에 대한 내용을 확인하려면 이 곳을 참고한다)

query : document

업데이트 할 도큐먼트의 선택 기준. 한번에 하나의 도큐먼트만 업데이트 가능함.

sort : document

업데이트 할 도큐먼트 선택. 도큐먼트의 정렬 순서를 정함.

update : document

"update" 또는 "remove" 둘 중 하나는 반드시 명시되어야 함. 두 개를 동시에 명시할 수는 없음. field: value 형태로 업데이트.

remove : boolean

"update" 또는 "remove" 둘 중 하나는 반드시 명시되어야 함. 두 개를 동시에 명시할 수는 없음. update field에 명시된 도큐먼트를 제거. 도큐먼트를 제거하려면 "true"로 설정함. 기본값은 "false"임.

new : boolean

"true"로 설정될 경우 원본을 업데이트 하는 것이 아닌 새로운 문서로 생성하여 업데이트 됨.


이번에는 다음을 입력하여 도큐먼트를 제거해 보자. 현재 DB 내용은 다음과 같다.

> db.tasks.find()
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250ac"), "priority" : "4", "status" : "RUNNING", "todo" : "shopping" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250ad"), "todo" : "studying Mongo DB", "status" : "READY", "priority" : "1" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250ae"), "todo" : "reporting the current job", "status" : "DONE", "priority" : "8" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250af"), "todo" : "cleaning my room", "status" : "READY", "priority" : "3" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250b0"), "todo" : "meeting friends", "status" : "DONE", "priority" : "7" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250b1"), "todo" : "depositing money", "status" : "RUNNING", "priority" : "6" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250b2"), "todo" : "take a walk", "status" : "RUNNING", "priority" : "5" }
{ "_id" : ObjectId("52ebb9ff5e3b86c2a73250b3"), "todo" : "sending an email", "status" : "READY", "priority" : "2" }

현재 완료된("status" : "DONE") 도큐먼트 중 우선순위가 가장 낮은 아이템을 삭제해 보자.

db.tasks.findAndModify({
	query : {status : "DONE"},
	sort : {priority : 1},
	remove : true
})

결과를 살펴보면

> db.tasks.find()
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250ac"), "priority" : "4", "status" : "RUNNING", "todo" : "shopping" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250ad"), "todo" : "studying Mongo DB", "status" : "READY", "priority" : "1" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250ae"), "todo" : "reporting the current job", "status" : "DONE", "priority" : "8" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250af"), "todo" : "cleaning my room", "status" : "READY", "priority" : "3" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250b1"), "todo" : "depositing money", "status" : "RUNNING", "priority" : "6" }
{ "_id" : ObjectId("52ebb9fe5e3b86c2a73250b2"), "todo" : "take a walk", "status" : "RUNNING", "priority" : "5" }
{ "_id" : ObjectId("52ebb9ff5e3b86c2a73250b3"), "todo" : "sending an email", "status" : "READY", "priority" : "2" }

예상대로 친구를 만나는(meeting friends) 일이 삭제되었음을 확인할 수 있을 것이다.

findAndModify가 "update" 명령에 비해 떨어지는 점은 속도이다. findAndModify가 약간 더 느리다.

Comments