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/

소셜 미디어로 공유하기

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

 

새 블로그로 이사갑니다.

 

rastalion.dev

 

도메인 변경했어요. 현재 지속적으로 개선 중입니다.

 

This will close in 10 seconds