본문 바로가기
Study/mongodb

05. MongoDB(몽고디비) Study - 데이터 읽기 (find)

by 블리드카가 2017. 10. 9.
728x90


 오늘은 Document를 읽어오는 명령어들에 대해 알아보겠습니다. 
 '04. MongoDB Study - 데이터 입력 (insert)' 글에서 입력한 데이터를 토대로 질의(query)를 실행해보겠습니다.

  1. find

find는 MongoDB에서 기본적인 읽기 명령어 입니다. 관계형 데이터 베이스에서 SELECT와 비교할 수 있습니다.
find명령어는 아래와 같은 구조로 되어 있습니다.

db.collection.find( query, projection ) 

query 부분은 데이터의 조건을 입력하는 object이며, projection 부분은 특정 필드를 보여줄지 설정할 수 있습니다.

하나씩 실습을 해보겠습니다.

아래는 SELECT * FROM employee 와 비교될 수 있는 Collection 전체 검색 명령입니다.
db.employee.find({}) 

    2. 동등 비교

employee Collection에서 status가 "C" 인 것만 선택해오겠습니다.
SELECT * FROM employee WHERE status = 'C' 와 같은 의미 입니다.
db.employee.find({status : "C"}) 
status 가 C 인 사람 중 이름만 가져오겠습니다.
SELECT ename FROM employee WHERE status = 'C' 와 같은 의미 입니다.
db.employee.find({status : "C"}, {ename : 1}) 


_id 값은 따라 오는 군요.  _id 값을 제거 하겠습니다. 불필요한 field의경우 _id 값처럼 0값으로 지정하면 됩니다.
db.employee.find({status : "C"}, {_id: 0, ename : 1}) 


    
3. 연산자 (Operator) 
조회를 할 때 여러가지의 연산자를 이용하여 조회 조건을 줄 수 있습니다.
{ <field1>: { <operator1>: <value1> }, ... }
    1) 비교연산자

동등 비교조건 에서 수행했던 status 값이 C 인 직원을 $eq 연산자를 사용하여 조회해보겠습니다.
db.employee.find({status : { $eq : "C"}}, {_id: 0, ename : 1}) 
 height 160 보다 큰 직원을 조회합니다.
db.employee.find({height : { $gt : 160}}) 
height  170보다 크거나 같은 직원을 조회합니다. 
db.employee.find({height : { $gte : 170}}) 

height가 170인 사람과 185인 직원을 조회합니다.
db.employee.find({height : { $in : [170, 185]}}) 
height가 170보다 작은 직원을 조회합니다.
db.employee.find({height : { $lt : 170}}) 
height가 170보다 작거나 같은 직원을 조회합니다.
db.employee.find({height : { $lte : 170}}) 
height가 170이 아닌 직원을 조회합니다.
db.employee.find({height : { $ne : 170}}) 
height가 170인 사람과 185가 아닌 직원을 조회합니다.
db.employee.find({height : { $nin : [170, 185]}}) 
  height가 170이상 185이하인 직원을 구합니다.
db.employee.find({height : {$gte : 170, $lte:185}})
 
비교 연산자 정리
이름 설명
$eq 값을 비교하여 동일한 값을 찾는 연산자
$gt 값을 비교하여 지정된 값보다 큰 값을 찾는 연산자
$gte 값을 비교하여 지정된 값보다 크거나 같은 값을 찾는 연산자
$in 배열 안의 값을 비교하여 동일한 값을 찾는 연산자
$lt 값을 비교하여 지정된 값보다 작은 값을 찾는 연산자
$lte 값을 비교하여 지정된 값보다 작거나 큰 값을 찾는 연산자.
$ne 값을 비교하여 동일하지 않은 값을 찾는 연산자
$nin
배열 안의 값을 비교하여 동일하지 않는 값을 찾는 연산자

    2) 논리 연산자

여러개의 조건이 모두 true인 조건을 구하는 $and 연산자

height가 170이상을 만족하고 status 가 C인 직원을 구합니다.
db.employee.find({ $and : [{height : {$gte : 170}}, { status : {$eq : "C"}}] })
 height가 170이상을 만족 하거나 status가 C인 직원을 구합니다.
db.employee.find({ $or : [{height : {$gte : 170}}, { status : {$eq : "C"}}] })
height 가 180이하가 아닌 사람을 구합니다.
db.employee.find({height : {$not : {$lte : 180}}})
 $not 연산자는
{ field: { $not: { <operator-expression> } } }
형식으로 되어 있습니다.

$not 연산자는 아래의 결과 값처럼 단순히 연산자의 값의 반대값뿐만 아니라 존재하지 않는 값까지 결과에 포함됩니다.




$nor 연산자도 있습니다. 부정논리합으로 모두 거짓인 경우를 결과 값에 나타냅니다.

논리 연산자 정리
이름 설명
$and 배열안 두개 이상의 조건이 모두 참인 경우를 반환 
$not 해당 조건이 맞지 않는 경우와 해당 필드가 없는 경우를 모두 반환
$nor 배열안 두개 이상의 조건이 모두 아닌 경우 를 반환
$or 배열안 두개 이상의 조건 중 하나라도 참이면 반환


   

    3) Embbedded Document(내장형문서) 조회

MongoDB에서는 JSON객체 형태의 문서로 데이터를 저장하는데 문서안에 다시 문서의 내장된 문서의 형태로도 데이터를 저장할 수 있습니다. 그러한 내장형 문서를 조회를 해보겠습니다. 

연습을 위해 아래의 데이터를 Insert 합니다.
db.inventory.insertMany( [ 
    { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" }
  , { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" }
  , { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" }
  , { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" }
  , { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
 ]);
 아래는 위에서 실습한 기본적인 형태의 동등 조건의 조회식입니다.
size가 h 14이며 w 가 21 uom 이 cm 인 값을 찾습니다.
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )

이러한 형태는 하위 문서와 완전히 똑같은 문서만 찾을 수 있습니다.

아래는  하위문서와 특정 필드에 조건을 걸어 구하는 식입니다. size 아래 문서 중 uom 값이 cm 인 값을 구하는 식입니다.
db.inventory.find( { "size.uom": "cm" } )
size 값 중 h값이 10보다 작은 값을 구합니다. 
db.inventory.find( { "size.h": {$lt : 10} } )
size 값 중 h값이 10보다 작고 status 가 A 인 문서를 구합니다.
db.inventory.find( { "size.h": {$lt : 10}, status : "A"} )

    4) 배열값 조회

MongoDB는 배열형태의 값을 저장할 수 있습니다. 

연습을 위해 아래의 데이터를 저장합니다.
db.inventory.insertMany([ 
    { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] }
, { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] }
, { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] }
, { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] }
, { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] } ]);
다음은 tags 필드에 오직 red값과 blank값만 배열에 존재하는 문서를 조회합니다.
db.inventory.find( { tags: ["red", "blank"] } )
위 경우는 red와 blank 만 포함된 경우만 출력합니다. 다른 것이 포함된 경우는 출력되지 않습니다.


다음은 tags값에 red와 blank 값이 모두 존재하는 문서를 조회합니다.
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
이 경우는  red와 blank를 포함하고 다른 것들이 포함된 경우도 함께 출력됩니다.


다음은 배열이 포함된 필드에 배열 조회가 아닌 단일 값만 조회 값으로 입력했을때의 결과를 보겠습니다.
db.inventory.find( { tags: "red"} )
위 결과는 red가 배열에 포함된 모든 문서를 출력합니다.

다음은 dim_cm 필드에 25이상 값이 포함된 문서를 출력합니다.
db.inventory.find( { dim_cm: {$gte : 25}} )
다음은 dim_cm필드에서 1번째 위치 즉 0번 인덱스에 있는 값 중 14이상인 값을 구합니다.
db.inventory.find( { "dim_cm.0": {$gte : 14}} )


다음은 tags 배열의 크기가 2인 문서를 조회합니다.
db.inventory.find( { tags : {$size : 2}} )
 5) Embbedded Document내에서 배열값 조회

연습을 위해 아래 데이터를 입력합니다.
db.inventory.insertMany( [ 
    { item: "journal", instock: [ { warehouse: "A", qty: 5 } , { warehouse: "C", qty: 15 } ] }
, { item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] }
, { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] }
, { item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] }
, { item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] } ]);

instock 필드에서 { warehouse : "A", qty : 5 } 값을 가지는  document를 조회합니다.
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )

그러면 아래의 식은 조회가 될까요?
db.inventory.find( { "instock": { qty: 5, warehouse: "A" } } )
위의 값은 조회가 되지 않습니다. 문서(객체)를 동등 비교하는 경우 순서 포함하여 모든 값이 일치해야합니다.

instock 1번째 배열의 qty 값이 40 이상인 값을 조회 하겠습니다.
db.inventory.find( { 'instock.0.qty': { $gte: 40 } } )
다음은  instock 필드에서 qty가 5이고 warehouse 값이 A인 문서를 조회합니다.  순서는 상관 없습니다.
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
    6) 조회 결과에서 필드 표시 여부

find 명령어 두번째 파라미터에서 field 를 표시할지 여부를 지정 합니다. 기본적으로 파라미터가 없으면 모두 표시 됩니다.

document 에  기본적으로 포함된 _id필드를 제외하고 나머지 필드의 경우 '표시할 필드만 입력' 하거나 '표시하지 않을 필드를 표시' 해야 합니다. 

즉 아래의 식은 에러가 발생합니다.
db.inventory.find( { status: "A" }, { item: 1, status: 0 } )
 아래의 식은 item 필드와, status 필드 그리고 _id필드가 표시 됩니다.
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
아래의 식은 item필드와 status필드를 제외한 필드가 표시됩니다.
db.inventory.find( { status: "A" }, { item: 0, status: 0 } )
 Embedded(내장) 된 문서의 필드 표시는 아래와 같습니다.
db.inventory.find( { status: "A" }, { item: 1, status: 1, "size.uom": 1 } )

    7) Null 값과 필드 존재여부 조회

아래의 식은 item 필드가 null 인 값도 조회 하지만, item 필드가 존재하지 않는 문서도 조회가 됩니다.
db.inventory.find( { item: null } )
item 필드가 존재하지 않는 문서를 조회합니다.
db.inventory.find( { item : { $exists: false } } )


이름 설명
$exists 특정 필드를 가지고 있으면 반환
$type 특정 타입의 필드가 있으면 반환

    8) Cursor 반복문

find 명령어는 cursor형태의 객체로 반환이 됩니다.
변수를 할당하고 아래와 같이 javascript 반복문을 활용할 수 있습니다.
var myCursor = db.users.find( { type: 2 } ); 
while (myCursor.hasNext()) 
{ 
    printjson(myCursor.next());
}

아래와 같이도 가능 합니다.
var myCursor = db.users.find( { type: 2 } ); 
myCursor.forEach(printjson);

cursor객체를 array(배열) 로 변환할 수 있습니다.
var myCursor = db.inventory.find( { type: 2 } ); 
var documentArray = myCursor.toArray(); 
var myDocument = documentArray[3];
728x90