Database/MongoDB

[MongoDB] 쿼리

Victory_HA 2022. 3. 31. 22:37

MongoDB 조회

Data 구조

dbs 조회 및 사용

> show dbs;
> use test-db;

컬랙션 조회

show collections;

JavaScript

  • mongoDB shell에서는 기본적인 JavaScript 명령어를 사용할 수 있다.
  • JSON 형태 데이터로 입출력하기 때문에, JSON형태 데이터를 저장,관리 할 수 있다.

예시

for(i=0; i<10; i++)
    print('hello');

실행 결과

0.insert data

  • 전체 예제 코드 파일

test.mongodb
0.01MB

  • 다음은 test-dbitem 컬렉션에 도큐먼트를 추가하는 예제이다.
//use db
use('test-db');

//remove all documents
db.item.remove({});

//insert documents
db.item.insert({num:1,name:"lsh 1",ticketno:[11,2,3]});
db.item.insert({num:2,name:"lsh 2",ticketno:[12,2,3]});
db.item.insert({num:3,name:"lsh 3",ticketno:[13,2,3]});
db.item.insert({num:4,name:"lsh 4",ticketno:[14,2,3]});
db.item.insert({num:5,name:"lsh 5",ticketno:[15,2,3]});
db.item.insert({num:1,name:"jyp 1",ticketno:[16,2,3]});
db.item.insert({num:2,name:"jyp 2",ticketno:[17,2,3]});
db.item.insert({num:3,name:"jyp 3",ticketno:[18,2,3]});
db.item.insert({num:4,name:"jyp 4",ticketno:[19,2,3]});
db.item.insert({num:5,name:"jyp 5",ticketno:[10,2,3]});

1.find

  • find를 사용하면 컬렉션에서 도큐먼트를 조회할 수 있다.
  • find의 매개변수를 지정하여 특정 조건의 도큐먼드를 조회할 수 있고,
  • 또는 조건없이 모든 도큐먼트를 조회할 수 있다.
  • 도큐먼트의 _id값은 항상 반환된다
//매개변수 1개
db.item.find({num:1});

//매개변수 2개
db.item.find({num:1,name:"lsh 1"});

컬렉션의 모든 도큐먼드 조회

  • 매개변수를 비워두거나, {}를 입력하면 컬렉션의 모든 도큐먼트를 반환한다.
// 이하 명령어는 동일하게 모든 도큐먼트 조회
> db.item.find();
> db.item.find({});

반환받을 키 지정

  • 반환 받은 도큐먼트에서 키/값 정보가 전부 필요하지 않을 수 있다.
  • 예를 들어 다음 도큐먼트에서 ticketno 만 표시하고 싶지 않다면,
db.item.insert({num:1,name:"lsh 1",ticketno:[11,2,3]});
  • find 혹은 findOne 의 2번째 매개변수에 0과 1로 해당 키값의 표시 여부를 정할 수 있다.
db.item.find({},{ticketno : 1});

결과

"_id": {
    "$oid": "618cf1204422ce4a95441a18"
},
"num": 1,
"name": "lsh 1"
  • _id를 제외하고 싶으면 다음과 같이 쿼리를 작성한다.
  • 키 값을 2개를 1,0 동시에 표시하는건 불가능한 듯 하다.
db.item.find({},{ticketno : 1, _id : 0});

2.쿼리

참조 : https://docs.mongodb.com/manual/reference/operator/query/

2.1 비교 쿼리

$lt, $lte, $gt, $gte

Syntax: { <field>: { $lt: <value> } }
  • 쿼리는 완전 일치 조건 외에도 비교연산자(<, <=, >, >=)를 $lt, $lte, $gt, $gte를 이용하여 사용할 수 있다.
    • less, great, than, equal 의 약자
// num의 값이 3 미만 값을 가진 필드 조회 
db.item.find({num:{$lt:3}}); 
// num의 값이 3 이하 값을 가진 필드 조회
db.item.find({num:{$lte:3}}); 
// num의 값이 3 초과 값을 가진 필드 조회 
db.item.find({num:{$gt:3}}); 
// num의 값이 3 이상 값을 가진 필드 조회
db.item.find({num:{$gte:3}});

$in

Syntax: { field: { $in: [<value1>, <value2>, ... <valueN> ] } }
  • 필드의 값이 $in 안에 들어있는 값들 중 하나인 필드를 찾습니다.
//조건 1개
db.item.find({"num":{"$in":[1,2]}});

$nin (Not IN)

Syntax: { field: { $nin: [ <value1>, <value2> ... <valueN> ]} }
  • 필드의 값이 $nin 안에 값들이 아닌 필드를 찾습니다.
db.item.find({"num":{"$nin":[1,2]}});

$eq (Equal)

Syntax: { <field>: { $eq: <value> } }
  • 해당 값과 일치하는 값을 가진 필드를 찾습니다.
db.item.find({num:{$eq:3}}); db.item.find({num:3});

$ne (Not Equal)

Syntax: {field: {$ne: value} }
  • 해당 값과 일치하지 않는 값을 가진 필드를 찾습니다.
db.item.find({num:{$ne:3}});

2.2 논리 쿼리

$or

Syntax: { $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }
  • 여러 개의 조건 중에 적어도 하나를 만족하는 도큐먼트를 찾습니다.
//조건 n개
db.item.find({"$or":[{"num":1},{"num":2},{"name":"lsh 3"}]})

$nor (Not OR)

Syntax: { $nor: [ { <expression1> }, { <expression2> }, ...  { <expressionN> } ] }
  • 여러 개의 조건을 모두 만족하지 않는 다큐먼트를 찾습니다.
db.item.find({$nor:[{"num":1},{"num":2},{"name":"lsh 3"}]})

$and

Syntax: { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
  • 여러 개의 조건을 모두 만족하는 도큐먼트를 찾습니다.
db.item.find({"$and":[{"num":1},{"name":"lsh 1"}]})

$not

Syntax: { field: { $not: { <operator-expression> } } }
  • 조건을 만족하지 않는 필드를 찾습니다.
  • 사용을 언제 어떻게 할 수 있나?
    • { field : {operator : value} } 다음과 같은 Syntax를 가진 쿼리에서 응용하여 사용 할 수 있다.
db.item.find({num:{$not:{$in:[1,2]}}});
db.item.find({num:{$not:{$lt:3}}});

2.3 형 특정 쿼리

$exists

Syntax: { field: { $exists: <boolean> } }
  • 해당 필드가 존재해야 하는지 존재하지 않아야 하는지를 정합니다.
  • null은 값이 null인 경우와, 아무것도 아닌 뜻의 null이 존재하므로 구분이 필요합니다.
//쿼리 - Exists
db.item.find({num : {$eq:1,$exists:true}});   // db.item.find({num :1});
db.item.find({num : {$exists : true}});       // num 있는 필드 출력
db.item.find({num : {$exists:false}});        // empty 없는 필드 출력
db.item.find({empty : null});    //empty가 없거나, empty가 null인 필드 출력
db.item.find({empty : {$eq:null , $exists : true}});     //empty의 value가 null 필드 출력
db.item.find({empty : {$eq:null , $exists : false}});    //empty가 없는 필드 출력

$regex

Syntax1 : { <field>: { $regex: /pattern/, $options: '<options>' } }
Syntax2 :{ <field>: { $regex: 'pattern', $options: '<options>' } }
Syntax3 :{ <field>: { $regex: /pattern/<options> } }
  • 정규표현식($regex)을 사용하여 pattern과 일치하는 데이터를 찾을 수 있다.
  • 다음 예제는 joe가 포함된 도큐먼트를 반환한다.
  • 정확히 joe만 찾는 예제는 찾아봐야 한다.
db.item.find({string:{$regex: /joe/, $options: 'i'}});      //pattern 1
db.item.find({string:{$regex: 'joe',$options : 'i'}});    //pattern 2
db.item.find({string:{$regex: /joe/i}});                  //pattern 3

2.4 배열 쿼리

  • 아래 같은 배열이 있다.
//데이터 추가 
db.item.insertOne({_id:1,fruit:["apple","banana"], size : 2}); 
db.item.insertOne({_id:2,fruit:["cherry","apple","mango"], size : 3}); 
db.item.insertOne({_id:3,fruit:["banana","cherry","apple"], size : 3}); 
db.item.insertOne({_id:4,fruit:["banana","cherry","apple","mango"], size : 4});
  • 다음 쿼리는 배열value 가 정확히 일치 할 때 찾는 방법이다.
db.item.find({fruit:["banana","cherry","apple"]});

%all

Syntax : { <field>: { $all: [ <value1> , <value2> ... ] } }
  • 2개 이상의 배열 요소가 포함돼있는 필드를 찾을 때 사용한다.
db.item.find({fruit:{$all : ["banana","apple"]}});      
db.item.find({fruit:{$all : ["banana","mango"]}});      // 두개 동시에 있는 필드 X

$size

  • 배열의 크기를 쿼리하는 조건절이다.
  • fruit 키가 가지는 배열 값 중 크기가 4인 필드만 반환한다.
  • db.item.find({fruit:{$size:4}});
  • 추가로 "size" key로 추가하고, size키의 값은 배열의 크기를 나타낸다고 하자.
  • 그럼 size키를 이용하여 $gt와 같은 비교 쿼리를 사용할 수 있다.
  • 다음은 size키를 가지고 있는 도큐먼트에서 값이 3이상인 필드만 찾는 예제이다.
db.item.find({size:{$gte : 3}});

$slice

Syntax1 : 
db.collection.find(
   <query>,
   { <arrayField>: { $slice: <number> } }
);

Syntax2 : 
db.collection.find(
   <query>,
   { <arrayField>: { $slice: [ <number>, <number> ] } }
);
  • 배열 요소의 일부를(부분집합) 반환받을 수 있다.
//데이터 추가
db.item.insertOne(
    {
        _id:6,
        title:"A post",
        comments:
        [
            {
                name : "joe",
                email : "joe@korea.com",
                content : "Nice post"
            },
            {
                name : "lee",
                email : "lee@korea.com",
                content : "Bad post"
            },
            {
                name : "viva",
                email : "viva@korea.com",
                content : "hi daddy "
            },
            {
                name : "gta",
                email : "gta@korea.com",
                content : "hello world"
            },
            {
                name : "jks",
                email : "jks@korea.com",
                content : "i love dog"
            },
            {
                name : "psj",
                email : "psj@korea.com",
                content : "docker compose is best"
            },
        ]
    });
db.item.findOne({ },{comments : {"$slice" : 2}});    // 앞에서 요소 2개
db.item.findOne({ },{comments : {"$slice" : -2}});   // 뒤에서 요소 2개
db.item.findOne({ },{comments : {"$slice" : [2,3]}});   // 요소 3번째 이후부터 요소 3개

2.5 $where 쿼리

Syntax : { $where: <string|JavaScript Code> }
  • 일반적으로 키/값으로도 다양한 쿼리가 가능하지만, 정확히 표현할 수 없는 쿼리도 있다.
  • where절을 사용하면 거의 모든 쿼리를 표현할 수 있다.
    • 거의 모든 쿼리가 가능하기 때문에 'end 유저'가 임의의 where절 사용을 보안상의 이유로 막아야한다.
  • where절은 두 키의 값을 비교할 때 자주 사용된다.
//데이터 추가
db.item.insertOne({apple : 1, banana : 6, peach : 3});
db.item.insertOne({apple : 8, spinach : 4, watermelon : 4});
  • 아래는 where절 안에 있는 자바스크립트이다.
  • 예를 들어, 두 번째 도큐먼트의 spinach, watermelon의 값은 동일하다.
  • 다음 쿼리는 두 필드의 값이 동일한 도큐먼트가 있는지 확인한다.
db.item.find({
    $where : function() 
    {
        for(var current in this){
            for(var other in this){
                if(current != other && this[current] == this[other]){
                    return true;        //값이 동일한 도큐먼트 있다.
                }
            }
        }
        return false;       //값이 동일한 도큐먼트 없다.  
    }
});
  • where절의 단점
    • 실행시 도큐먼트가 BSON -> 자바스크립트 객체로 변환되어, 일반 쿼리보다 속도가 느리다.
    • 인덱스를 쓸 수 없다.
  • where절의 단점을 보완한 $expr을 사용하자.
    • 자바스크립트를 실행하지 않아 속도가 빠르다.

2.6 커서

  • 개인적으로 이해한 내용은 도큐먼트의 반환 값들을 변수에 넣은 후 해당 변수를 이용하여 데이터를 가공하여 다시 획득하도록 이용할 수 있다.
//데이터 추가
//insert documents - Cursor
db.item.insert({num:8,name:"hjyp 3"});
db.item.insert({num:3,name:"clsh 3"});
db.item.insert({num:4,name:"dlsh 4"});
db.item.insert({num:1,name:"alsh 1"});
db.item.insert({num:2,name:"blsh 2"});
db.item.insert({num:6,name:"fjyp 1"});
db.item.insert({num:7,name:"gjyp 2"});
db.item.insert({num:5,name:"elsh 5"});
db.item.insert({num:9,name:"ijyp 4"});
db.item.insert({num:10,name:25});
hasnext()
var cur = db.item.find();
cur;
cur.hasNext();
cur.next()
cur.next()
cur.next()

cursor - sort
var cur = db.item.find();
cur.sort({name:-1}); //역순 정렬

//cursor - limit
var cur = db.item.find();
cur.limit(3);    //3개만 표시

//cursor - advanced
var cur = db.item.find();
cur.sort({name:-1}).limit(5),skip(2);

//cursor - advanced2
var cur = db.item.find();
while(cur.hasNext()) printJson(cur.next());

'Database > MongoDB' 카테고리의 다른 글

[MongoDB] MongoDB 기본 개념  (0) 2022.03.31