MongoDB Document 조회하기
MongoDB 도큐먼트 조회하기
find() 명령은 컬렉션 안에 도큐먼트들을 넣었으면, 필요할 때 조회를 할 수 있어야 합니다. 조회를 할때 사용하는 명령입니다.
> db.COLLECTION_NAME.find( <query>, <projection> )
Parameter | Type | Describtion |
query | document | Optional. 쿼리 연산자를 이용해 원하는 도큐먼트를 선택. |
projection | document | Optional. return할 필드를 선택할 수 있다. |
우선 그동안 만들었던 Collection이 뭐가 있는지 보겠습니다.
> show collections cappedCollection myCollection user
3개의 컬렉션이 존재하고, user 컬렉션의 모든 도큐먼트를 조회해보도록 하겠습니다.
> db.user.find() { "_id" : ObjectId("5f504be9fc907fec200b55ad"), "username" : "karoid", "password" : "1111" } { "_id" : ObjectId("5f504dedfc907fec200b55ae"), "username" : "John", "password" : 4321 } { "_id" : ObjectId("5f504dedfc907fec200b55af"), "username" : "K", "password" : 4221 } { "_id" : ObjectId("5f504dedfc907fec200b55b0"), "username" : "Mark", "password" : 5321 } { "_id" : ObjectId("5f50a274237701f054a0e52e"), "userID" : "kimikimi", "username" : "Kim", "password" : 1111 } { "_id" : ObjectId("5f51894e237701f054a0e52f"), "username" : "Kei", "password" : 4321 } { "_id" : ObjectId("5f51894e237701f054a0e530"), "username" : "Mijoo", "password" : 3212 } { "_id" : ObjectId("5f51894e237701f054a0e531"), "username" : "Yein", "password" : 3123 }
많은 데이터가 들어가 있네요.
> db.user.find().pretty() { "_id" : ObjectId("5f504be9fc907fec200b55ad"), "username" : "karoid", "password" : "1111" } { "_id" : ObjectId("5f504dedfc907fec200b55ae"), "username" : "John", "password" : 4321 } { "_id" : ObjectId("5f504dedfc907fec200b55af"), "username" : "K", "password" : 4221 } { "_id" : ObjectId("5f504dedfc907fec200b55b0"), "username" : "Mark", "password" : 5321 } { "_id" : ObjectId("5f50a274237701f054a0e52e"), "userID" : "kimikimi", "username" : "Kim", "password" : 1111 } { "_id" : ObjectId("5f51894e237701f054a0e52f"), "username" : "Kei", "password" : 4321 } { "_id" : ObjectId("5f51894e237701f054a0e530"), "username" : "Mijoo", "password" : 3212 } { "_id" : ObjectId("5f51894e237701f054a0e531"), "username" : "Yein", "password" : 3123 }
명령에 끝에 pretty()를 넣으면 좀 더 보기가 편해집니다.
쿼리 (Query)
쿼리는 데이터베이스 속의 수 많은 정보 속에서 원하는 정보를 찾아내도록 도와주는 필터같은 역할을 합니다.
다음 예제는 유저명이 Yein인 도큐먼트를 찾아오는 쿼리입니다.
> db.user.find({username: "Yein"}) { "_id" : ObjectId("5f51894e237701f054a0e531"), "username" : "Yein", "password" : 3123 }
RDBMS 데이터베이스에서 select 구문은 사용할때 다양한 조건절과 연산자를 사용할 수 있는데, MongoDB에서는 원하는 데이터를 찾기 위해 연산자를 사용합니다. 연산자의 종류는 비교(Comparison), 논리(Logical), 요소(Element), 배열(Array) 등 여러종류가 있습니다.
다음은 만이 사용하는 연산자 입니다.
비교(Comparison)
Operator | Describtion |
---|---|
$eq | (equals) 주어진 값과 일치하는 값 |
$gt | (greater than) 주어진 값보다 큰 값 |
$gte | (greather than or equals) 주어진 값보다 크거나 같은 값 |
$lt | (less than) 주어진 값보다 작은 값 |
$lte | (less than or equals) 주어진 값보다 작거나 같은 값 |
$ne | (not equal) 주어진 값과 일치하지 않는 값 |
$in | 주어진 배열 안에 속하는 값 |
$nin | 주어빈 배열 안에 속하지 않는 값 |
논리(Logical)
Operator | Describtion |
---|---|
$or | 주어진 조건중 하나라도 true 일 때 true |
$and | 주어진 모든 조건이 true 일 때 true |
$not | 주어진 조건이 false 일 때 true |
$nor | 주어진 모든 조건이 false 일때 true |
$regex 연산자
$regex 연산자를 통하여 Document를 정규식을 통해 찾을 수 있습니다. 이 연산자는 다음과 같이 사용합니다.
{ <field>: { $regex: /pattern/, $options: '<options>' } } { <field>: { $regex: 'pattern', $options: '<options>' } } { <field>: { $regex: /pattern/<options> } } { <field>: /pattern/<options> }
Option | Describtion |
---|---|
i | 대소문자 무시 |
m | 정규식에서 anchor(^) 를 사용 할 때 값에 \n 이 있다면 무력화 |
x | 정규식 안에있는 whitespace를 모두 무시 |
s | dot (.) 사용 할 떄 \n 을 포함해서 매치 |
$where 연산자
$where 연산자를 통하여 javascript expression 을 사용 할 수 있습니다.
프로젝션 (Projection)
find() 메소드의 두번째 parameter 인 projection에 대하여 알아보도록 하겠습니다. 쿼리의 결과값에서 보여질 field를 정합니다.
프로젝션을 이용햐소 도큐먼트의 모든 필드를 불러오지 않고 원하는 필드만 가져오게 되면 불러오는 정보의 양을 줄여서 응답속도를 높일수 있습니다.
_id 값은 조회하지 않고, 유저명과 패스워드만 조회 하는 예제입니다.
> db.user.find( { } ,{ "_id": false, "username": true, "password": true} ) { "username" : "karoid", "password" : "1111" } { "username" : "John", "password" : 4321 } { "username" : "K", "password" : 4221 } { "username" : "Mark", "password" : 5321 } { "username" : "Kim", "password" : 1111 } { "username" : "Kei", "password" : 4321 } { "username" : "Mijoo", "password" : 3212 } { "username" : "Yein", "password" : 3123 }
다음은 유저 네임만 가져오는 프로젝션입니다.
> db.user.find( null, {"_id":false, "username":true} ) { "username" : "karoid" } { "username" : "John" } { "username" : "K" } { "username" : "Mark" } { "username" : "Kim" } { "username" : "Kei" } { "username" : "Mijoo" } { "username" : "Yein" }
프로젝션을 설정할 때에는 _id 필드를 제외한 필드들의 설정값이 true 혹은 false로 모두 통일되어야 합니다. 그래야지만 출력이 됩니다.
더 많은 쿼리와 프로젝션 연산자는 MongoDB의 Docs(https://docs.mongodb.com/manual/reference/operator/query/)에서 확인이 가능합니다.
점 연산자
MongoDB에서 오브젝트 안에 들어있는 값을 불러오기 위해서는 점 연산자를 이용해서 접근이 가능합니다.
var 명령으로 변수 선언을 할 수 있습니다.
> var unp = { name: {username: "Yein", password: 3123}} > > unp.name { "username" : "Yein", "password" : 3123 } > > unp.name.username Yein
이런식으로 값만 “username” : “Yein” 항목을 다불러오는 것이 아니라 Yein이라는 이름 항목만 가져오는 것 입니다.
ReadConcern
Replication set에서 더 정확한 값을 읽어오기 위해 필요한 설정 값입니다.
커서 (cursor)
쿼리 결과에 대한 포인터입니다. find 명령은 결과로 도큐먼트를 직접 반환하지 않고 커서를 반환합니다. 해당 도큐먼트의 위치 정보만을 반환하여 작업을 효율적으로 만들 수 있습니다. 데이터를 전부 불러올 도큐먼트만 선별적으로 조회할 수 있습니다. 커서는 결과값을 읽는 작업을 위해 필요한 것이기 때문에 10분이 지나면 비활성 상태로 전환됩니다.
cursor를 사용하는 이점은 컬렉션 전체 데이터를 모두 순환 하지만 Node에서는 1개씩의 document 만 가져와 처리하고 GC 되므로 메모리 사용을 최소화 하며 MongoDB에 순간적인 부하도 주지 않습니다. 때문에 대량의 데이터를 처리하는데 적합합니다.
> var cursor = db.user.find() > cursor { "_id" : ObjectId("5f504be9fc907fec200b55ad"), "username" : "karoid", "password" : "1111" } { "_id" : ObjectId("5f504dedfc907fec200b55ae"), "username" : "John", "password" : 4321 } { "_id" : ObjectId("5f504dedfc907fec200b55af"), "username" : "K", "password" : 4221 } { "_id" : ObjectId("5f504dedfc907fec200b55b0"), "username" : "Mark", "password" : 5321 } { "_id" : ObjectId("5f50a274237701f054a0e52e"), "userID" : "kimikimi", "username" : "Kim", "password" : 1111 } { "_id" : ObjectId("5f51894e237701f054a0e52f"), "username" : "Kei", "password" : 4321 } { "_id" : ObjectId("5f51894e237701f054a0e530"), "username" : "Mijoo", "password" : 3212 } { "_id" : ObjectId("5f51894e237701f054a0e531"), "username" : "Yein", "password" : 3123 } > cursor.hasNext() false
find 명령어를 실행하면 batch라는 곳에 검색한 결과를 모아 놓습니다. 상황에 따라 다르지만 일반적인 상황에서는 101(또는 그 이하)개의 도큐먼트를 batch에 모아놓고 20개씩 커서가 가르킵니다. 다음 한개의 도튜먼트를 불러오기 위해서는 next()로 호출할 수 있습니다.
> var cursor = db.cappedCollection.find() > cursor { "_id" : ObjectId("5f5049adfc907fec200b5474"), "x" : 690 } { "_id" : ObjectId("5f5049adfc907fec200b5475"), "x" : 691 } { "_id" : ObjectId("5f5049adfc907fec200b5476"), "x" : 692 } { "_id" : ObjectId("5f5049adfc907fec200b5477"), "x" : 693 } { "_id" : ObjectId("5f5049adfc907fec200b5478"), "x" : 694 } { "_id" : ObjectId("5f5049adfc907fec200b5479"), "x" : 695 } { "_id" : ObjectId("5f5049adfc907fec200b547a"), "x" : 696 } { "_id" : ObjectId("5f5049adfc907fec200b547b"), "x" : 697 } { "_id" : ObjectId("5f5049adfc907fec200b547c"), "x" : 698 } { "_id" : ObjectId("5f5049adfc907fec200b547d"), "x" : 699 } { "_id" : ObjectId("5f5049adfc907fec200b547e"), "x" : 700 } { "_id" : ObjectId("5f5049adfc907fec200b547f"), "x" : 701 } { "_id" : ObjectId("5f5049adfc907fec200b5480"), "x" : 702 } { "_id" : ObjectId("5f5049adfc907fec200b5481"), "x" : 703 } { "_id" : ObjectId("5f5049adfc907fec200b5482"), "x" : 704 } { "_id" : ObjectId("5f5049adfc907fec200b5483"), "x" : 705 } { "_id" : ObjectId("5f5049adfc907fec200b5484"), "x" : 706 } { "_id" : ObjectId("5f5049adfc907fec200b5485"), "x" : 707 } { "_id" : ObjectId("5f5049adfc907fec200b5486"), "x" : 708 } { "_id" : ObjectId("5f5049adfc907fec200b5487"), "x" : 709 } Type "it" for more > cursor.next() { "_id" : ObjectId("5f5049adfc907fec200b5488"), "x" : 710 } > cursor.hasNext() true >
hasNext()로 호출하면 출력한 도큐먼트가 더이상 없을때 false, 남아 있을때 true를 반환합니다.
커서를 이용한 도큐먼트 반환
일반적으로 find 명령을 사용했을때 모든 도큐먼트를 불러오지는 않습니다. it를 입력하면 추가적으로 도큐먼트를 20개씩 출력합니다.
> db.cappedCollection.find() { "_id" : ObjectId("5f5049adfc907fec200b5474"), "x" : 690 } { "_id" : ObjectId("5f5049adfc907fec200b5475"), "x" : 691 } { "_id" : ObjectId("5f5049adfc907fec200b5476"), "x" : 692 } { "_id" : ObjectId("5f5049adfc907fec200b5477"), "x" : 693 } { "_id" : ObjectId("5f5049adfc907fec200b5478"), "x" : 694 } { "_id" : ObjectId("5f5049adfc907fec200b5479"), "x" : 695 } { "_id" : ObjectId("5f5049adfc907fec200b547a"), "x" : 696 } { "_id" : ObjectId("5f5049adfc907fec200b547b"), "x" : 697 } { "_id" : ObjectId("5f5049adfc907fec200b547c"), "x" : 698 } { "_id" : ObjectId("5f5049adfc907fec200b547d"), "x" : 699 } { "_id" : ObjectId("5f5049adfc907fec200b547e"), "x" : 700 } { "_id" : ObjectId("5f5049adfc907fec200b547f"), "x" : 701 } { "_id" : ObjectId("5f5049adfc907fec200b5480"), "x" : 702 } { "_id" : ObjectId("5f5049adfc907fec200b5481"), "x" : 703 } { "_id" : ObjectId("5f5049adfc907fec200b5482"), "x" : 704 } { "_id" : ObjectId("5f5049adfc907fec200b5483"), "x" : 705 } { "_id" : ObjectId("5f5049adfc907fec200b5484"), "x" : 706 } { "_id" : ObjectId("5f5049adfc907fec200b5485"), "x" : 707 } { "_id" : ObjectId("5f5049adfc907fec200b5486"), "x" : 708 } { "_id" : ObjectId("5f5049adfc907fec200b5487"), "x" : 709 } Type "it" for more > > > > it { "_id" : ObjectId("5f5049adfc907fec200b5488"), "x" : 710 } { "_id" : ObjectId("5f5049adfc907fec200b5489"), "x" : 711 } { "_id" : ObjectId("5f5049adfc907fec200b548a"), "x" : 712 } { "_id" : ObjectId("5f5049adfc907fec200b548b"), "x" : 713 } { "_id" : ObjectId("5f5049adfc907fec200b548c"), "x" : 714 } { "_id" : ObjectId("5f5049adfc907fec200b548d"), "x" : 715 } { "_id" : ObjectId("5f5049adfc907fec200b548e"), "x" : 716 } { "_id" : ObjectId("5f5049adfc907fec200b548f"), "x" : 717 } { "_id" : ObjectId("5f5049adfc907fec200b5490"), "x" : 718 } { "_id" : ObjectId("5f5049adfc907fec200b5491"), "x" : 719 } { "_id" : ObjectId("5f5049adfc907fec200b5492"), "x" : 720 } { "_id" : ObjectId("5f5049adfc907fec200b5493"), "x" : 721 } { "_id" : ObjectId("5f5049adfc907fec200b5494"), "x" : 722 } { "_id" : ObjectId("5f5049adfc907fec200b5495"), "x" : 723 } { "_id" : ObjectId("5f5049adfc907fec200b5496"), "x" : 724 } { "_id" : ObjectId("5f5049adfc907fec200b5497"), "x" : 725 } { "_id" : ObjectId("5f5049adfc907fec200b5498"), "x" : 726 } { "_id" : ObjectId("5f5049adfc907fec200b5499"), "x" : 727 } { "_id" : ObjectId("5f5049adfc907fec200b549a"), "x" : 728 } { "_id" : ObjectId("5f5049adfc907fec200b549b"), "x" : 729 } Type "it" for more
toArarry()를 사용하면 모두 불러옵니다.
> db.cappedCollection.find().toArray() [ { "_id" : ObjectId("5f5049adfc907fec200b5474"), "x" : 690 }, { "_id" : ObjectId("5f5049adfc907fec200b5475"), "x" : 691 }, { "_id" : ObjectId("5f5049adfc907fec200b5476"), "x" : 692 }, { "_id" : ObjectId("5f5049adfc907fec200b5477"), "x" : 693 }, { "_id" : ObjectId("5f5049adfc907fec200b5478"), "x" : 694 }, { "_id" : ObjectId("5f5049adfc907fec200b5479"), "x" : 695 }, { "_id" : ObjectId("5f5049adfc907fec200b547a"), "x" : 696 }, { "_id" : ObjectId("5f5049adfc907fec200b547b"), "x" : 697 }, ... (중략) { "_id" : ObjectId("5f5049adfc907fec200b55a6"), "x" : 996 }, { "_id" : ObjectId("5f5049adfc907fec200b55a7"), "x" : 997 }, { "_id" : ObjectId("5f5049adfc907fec200b55a8"), "x" : 998 }, { "_id" : ObjectId("5f5049adfc907fec200b55a9"), "x" : 999 } ] >
반대로 forEach() 메소드를 사용하면 순차적으로 하나의 도큐먼트를 불러와서 작업 할 수 있습니다. 하나씩 불러와서 처리하기 때문에 메모리 사용이 많지 않습니다.
> db.cappedCollection.find().forEach(function(document){ 작업 ...})
forEach의 파라미터로 콜백 함수를 가지게 되는데, 콜백 함수 내에서 각각의 도큐먼트 변수에 담긴 도큐먼트들을 처리할 수 있습니다.
참고 자료
도서 : 맛있는 몽고DB
도서: Real MongoDB
도서: 오픈소스 몽고DB
도서: MongoDB in Action
MongoDB Manual: https://docs.mongodb.com/manual/
최신 댓글