반응형

1. 데이터베이스 백업

- 백업을 위한 명령어  : mongodump

• dumps the entire data of your server into the dump directory

   (서버의 전체 데이터를 덤프 디렉토리에 덤프)

• 백업 단위 선택 가능 : 컬렉션/데이터베이스/전체 데이터베이스 단위

 

ex) mongod 서버가 로컬호스트(포트# : 27017)에서 동작 중인 경우

• mongodb가 설치된 bin 폴더로 이동 후 mongodump 명령 입력

• 모든 데이터를 BSON 파일 형식으로 /bin/dump 폴더에 백업 수행

 

- mongodump와 함께 쓰는 옵션

 

Syntax Description Example
mongodump --host HOST_NAME --port PORT_NUMBER

This commmand will backup all databases of specified mongod instance.

(지정된 mongod 인스턴스의 모든 데이터베이스를 백업)

mongodump --host tutorialspoint.com --port 27017
mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY

This command will backup only specified database at specified path.

( 지정된 경로에서 지정된 데이터베이스 만 백업)

mongodump --dbpath /data/db/ --out /data/backup/
mongodump --collection COLLECTION --db DB_NAME

This command will backup only specified collection of specified database.

(지정된 데이터베이스 모음만 백업)

mongodump --collection mycol --db test

 

2. 백업된 데이터 복원(restore)  명령 : mongorestore

• restores all of the data from the backup directory

 

##mongodump and mongostore are not ideal for capturing backups of larger systems.

(위 두 명령어는 큰 시스템의 백업 캡쳐에 적합하지 않다)

 

3. Relationship

• represents how various documents are logically related to each other

(다양한 문서가 서로 논리적으로 어떻게 연관되어 있는지 나타낸다)

• can be either 1:1, 1:N, N:1 or N:N

• can ne modeled via Embedded and Referenced approaches.

(embedded 및 referenced 접근 방식을 통해 모델링)

 

ex) 사용자의 주소 저장하는 경우 (여러 개의 주소 가능 -> 1:N 관계 성립)

{ "_id":ObjectId("52ffc33cd85242f436000001"),
"name": "Tom Hanks",
"contact": "987654321",
"dob": "01-01-1991" } //USER
{"_id":ObjectId("52ffc4a5d85242602e000000"),
"building": "22 A, Indiana Apt",
"pincode": 123456, "city": "Los Angeles",
"state": "California" } //Address

1) Embedded Relationships = denormalized relationship 

• maintains all the related data in a single document, which makes it easy to retrieve and maintain

(모든 관련 데이터를 단일 문서로 유지 관리하여 쉽게 사용할 수 있도록 한다(회수 하여 유지))

 

{
"_id":ObjectId("u001"),
"name": "Tom Hanks", . . .
"address": [ { "building": "22 A, Indiana Apt", . . . },
                        { "building": "170 A, Acropolis Apt", . . . } ] }
                      ]
}

whole document can be retrieved in a single query

(전체 문서는 단일 쿼리로 검색할 수 있다)

db.users.findOne({"name":"Tom Hanks"},{"address":1})

• drawback(단점)

– if the embedded document keeps on growing too much in size, it can impact the read/write performance.

(포함된 문서의 크기가 계속 커지면 읽기 / 쓰기 성능에 영향을 미칠 수 있다)

 

 2) Referenced Relationships (참조 관계)= normalized relationship(정상화 관계)

• both the user and address documents will be maintained separately but the user document will contain a field that will reference the address document's id field.

(사용자 문서와 주소 문서는 별도로 유지되지만, 사용자 문서에는 주소 문서의 ID 필드를 참조하는 필드가 포함)

{
"_id":ObjectId("u001"),
. . .
"name": "Tom Hanks",
"address_ids": [ ObjectId("a001"), ObjectId("a002") ]
}

• need two queries: first to fetch the address_ids fields from user document and second to fetch these addresses from address collection.

(두 가지 쿼리가 필요 / 첫째는 사용자 문서에서 address_ids 필드를 가져오는 것 => 둘 째는 주소 집합에서 이 주소를 가져오는 것)

> var result = db.users.findOne({"name":"Tom Hanks"}, {"address_ids":1})
> db.address.find({"_id":{"$in":result["address_ids"] }})
//result 문서에서 address_ids 필드의 값만 추출 [ObjectId("a001"), ObjectId("a002")]

4. Database References

1)  For many use cases in MongoDB(몽고디비의 많은 사용 사례)

      • the denormalized data model where related data is stored within a single document will be optimal (embedded reltaionship)(관련 데이터가 저장되는 공식화된 데이터 모델 : 단일 문서가 최적 / 임베디드 Relationship)

      • in some cases, it makes sense to store related information in separate documents, typically in different collections or databases (normalized relationship)

            (경우에 따라 관련 정보를 별도로 저장하는 것이 타당 / 일반적으로 서로 다른 컬렉션 또는 DB 에 있는 문서(정규화된 관계))

 

2) two methods for relating documents in mongoDB applications(몽고디비 응용프로그램에서 Document와 관련된 2가지)

      • Manual references(수동 참조)

         – you save the _id field of one document in another document as a reference.
            Then your  application can run a second query to return the related data.

            (하나의 document에 id 필드를 저장하고 다른 document에서 참조하면 된다 
               / 응용프로그램에서 두 번째 쿼리를 실행하여 반환할 수 있다)

         – simple and sufficient method for most use cases.

             (대부분의 사용 사례에 대한 간단하고 충분한 방법)

      • DBRefs

      – references from one document to another using the value of the first document‟s _id field, collection name, and,             optionally, its database name

        (dbrefs를 사용하여 한 문서에서 다른 문서로 참조 /  _id 필드, 컬렉션 이름 및 데이터베이스 이름(선택 사항) 등이 있다)

      – in cases where a document contains references from different collections, we can use this method

         (document에 다른 collection이 포함되어 있다면 , 위의 방법을 사용한다)

 

3) Using DBRefs

• $ref 필드 : 참조되는 문서가 속한 컬렉션 이름↓

• $id 필드 : 참조되는 문서의 _id 필드

• $db 필드 : 참조되는 문서가 속한 데이터베이스 이름 (옵션)

아래 방향으로 필드 순서 주의 해서 사용해야한다.

 

{
"_id":ObjectId("53402597d852426020000002"),
"address": {
          "$ref": "address_home",
          "$id": ObjectId("534009e4d852427820000002"),
          "$db": "tutorialspoint"},
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Hanks" 
}
> var user = db.users.findOne({"name":"Tom Hanks"})
> var dbRef = user.address
> db[dbRef.$ref].findOne({"_id":(dbRef.$id)})

 

 

5. Covered Queries

1) covered query

• 인덱스만 이용해서도 처리가 가능한 질의 (데이터베이스 접근 없음)

• a query that can be satisfied entirely using an index and does not have to examine any documents

(인덱스를 사용하여 완전히 만족할 수 있고, 그 어떤 document도 검토할 필요가 없는 질의)

• 질의 처리에 필요한 모든 데이터가 인덱스에 있을 때 „이 인덱스가 해당 질의를 커버 한다‟라고 함

• An index covers a query when all of the following apply:(모두 적용되면 index는 query를 다룬다)

       – all the fields in the query are part of an index, and(쿼리의 모든 필드는 index의 일부분)

       – all the fields returned in the results are in the same index(결과에 반환되는 모든 필드가 동일한 index에 있음)

       – no fields in the query are equal to null(쿼리에 null과 동일한 필드가 없음)

 

{
"_id": ObjectId("53402597d852426020000002"),
"contact": "987654321",
"dob": "01-01-1991",
"gender": "M",
"name": "Tom Benzamin",
"user_name": "tombenzamin"
}

First. create a compound index for the users collection on the fields gender and user_name using the following query 

>db.users.ensureIndex({gender:1,user_name:1})

this index will cover the following query

>db.users.find({gender:"M"},{user_name:1,_id:0}) //ID필드는 결과 문서에서 반드시 제외시켜야 함

 

 

6. Analyzing Queries

-  Analyzing queries is a very important aspect of measuring how effective the database and indexing design is.

(쿼리 분석하는 것은 효과적으로 데이터베이스와 인덱스를 디자인하는데 있어 매우 중요한 측면)

1) $explain( ) 연산자

    • provides information on the query, indexes used in a query and other statistics

    (쿼리에 대한 정보, 쿼리에 사용된 인덱스 및 기타 통계 제공)

    • very useful when analyzing how well your indexes are optimized

    (인덱스가 얼마나 최적화 되어있는지 분석할 때 유용)

    • 사용 예)

> db.users.find({gender:"M"},{name:1, _id:0}).explain()
결과 
>{ "cursor" : "BtreeCursor gender_1_user_name_1", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 0, "nscanned" : 1, "nscannedObjectsAllPlans" : 0, "nscannedAllPlans" : 1, "scanAndOrder" : false, "indexOnly" : true, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { "gender" : [ [ "M", "M" ] ], "user_name" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ] } }

2) $hint( ) 연산자

    • forces the query optimizer to use the specified index to run a query

       (쿼리 최적화가 지정된 인덱스를 사용하여 쿼리를 실행하도록 강제 적용)

    • particularly useful when you want to test performance of a query with different indexes

       (다른 인덱스로 쿼리 성능을 테스트하는데 유용)

    • 사용 예)

>db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})

 

7. Atomic Operations

1) MongoDB provides atomic operations on only a single document

(몽고디비는 단일 document)에서만 atomic operations 을 제공

2) The recommended approach to maintain atomicity(원자성 유지하기 위한 권장하는 접근법)

    • keep all the related information, which is frequently updated together in a single document using embedded     documents(임베디드 문서를 사용하여 단일 문서로 자주 업데이트 되는 모든 관련 정보를 보관)

 =>  all the updates for a single document are atomic.(단일 document 에 대한 모든 업데이트는 원자적)

     • findAndModify 명령의 활용 예)

{ "_id":1,
             "product_name": "Samsung S3",
             "product_available": 3,
             "product_bought_by": [{ "customer": "john", "date": "7-Jan-2014"}, { "customer": "mark", "date": "8-Jan-2014"} ] }
> db.products.findAndModify({
            query:{_id:2,product_available:{$gt:0}},
            update:{ $inc:{product_available:-1},
                             $push:{product_bought_by:{customer:"rob",date:"9-Jan-2014"}} }
})

8. Advanced Indexing

{
"address": {
            "city": "Los Angeles",
            
"state": "California",
             "pincode": "123"
            
},
"tags": [
            
"music",
            
"cricket",
            
"blogs"
            
],
"name": "Tom Benzamin"
}

1) 배열을 필드 값으로 가지는 인덱싱 : multikey index 로 구성

multikey index 

– 배열의 각 요소 마다 인덱스 엔트리 유지

    =>  같은 배열에서 생성된 여러 엔트리들은 동일한 문서를 참조(포인트)

  user tag를 기반으로 user document를 검색한다 가정 / collection의 tag 배열에 index를 생성

 배열에 index 작성 시 , 각 필드에 대한 별도 index 항목이 작성 

==> 태그 배열에서 index 생성 시, music/ cricket / blogs 값에 대해 별도의 index 생성

 

> db.users.createIndex({"tags":1})
//태그 배열에 index 생성 
> db.users.find({"tags":"cricket"})
//index 생성 후 컬렉션의 태그 필드 검색 
> db.users.find({"tags":"cricket"}).explain()
//적절하게 사용되었는지 확인하려면 explain 명령 사용

"cursor": "BtreeCursor tags_1"//결과

 

2) 서브 문서를 필드 값으로 갖는 인덱싱

– 서브 문서의 모든 필드들에 대한 인덱스 생성 =>  compound index로 구성

도시 , 주 및 핀코드 필드 기반 문서 검색 / 

   => 모든 필드는 주소, 하위 문서 필드의 일부 이므로 -> 하위 문서의 모든 필드에 대한 index 생성

db.users.createIndex({"addr.city":1},{"addr.state":1}, {"addr.pincode":1})
//하위 문서의 세 필드 모두에 대한 index 
db.users.find({"addr.city":"LA"})
//index을 사용하는 하위 문서 필드 검색 가능 
db.users.find({"addr.city":"LA", "addr.state":1})
//쿼리 식은 지정된 index 순서를 따라야함 
db.users.find({"addr.city":"LA", "addr.state":1, "addr.pincode":1})

 

반응형
반응형

1. 데이터베이스 파티셔닝 (Database partitioning)

  • 데이터베이스를 분리하여 여러 서버에 분산, 저장 및 관리하는 기술
  • 파티셔닝 유형 (2가지)
    • 수직 파티셔닝 (vertical) 
      • 하나의 테이블의 컬럼들을 여러 테이블로 분리하는 방법
      • ex) R(A1, A2, A3, A4, A5)  == > R1(A1, A2, A3, A4) / R2(A1, A5)
    • 수평 파티셔닝(=샤딩)(horizontal)
      • 로우 (문서) 별로 데이터베이스를 분할하는 방법
      • 샤드(shard) : 분할된 각 데이터 조각 의미. 둘 이상의 서버에 분산 저장

2. Sharding in mongoDB(목적 : 데이터 분산 저장(부하 분산) / 백업, 복구 전략(안정적) / 빠른 처리 성능)

- 시스템이 더 이상 부하를 견디지 못할 때, Sharding 을 통해 가용성을 늘려주고, 버틸 수 있는 throughput도 늘려준다

- a method for distributing data across multiple machines by horizontal scaling to meet the demands of data growth

- adds more machines (scale out ) to support data growth and the demands of read and write operations

- for storage and load distribution

 

 

- 왜 샤딩을 사용하나?

  • In replication, all writes go to master node
  • Latency sensitive queries still go to master
  • Single replica set has limitation of 12 nodes
  • Memory can't be large enough when active dataset is big
  • Local disk is not big enough
  • Vertical scaling is too expensive

 

 

  • shard: Each shard contains a subset of the sharded data. Each shard can be deployed as a replica set.
    • 각 샤드에는 샤드 데이터의 하위 집합이 포함 / 각 샤드는 replica set로 배치한다.(고가용성 위해)
    • sharded cluster 안에서 sharded data의 subset을 가진다 
    • clusert의 shard 들에 존재하는 데이터를 합하면 원본의 데이터가 된다. 
    • 하나의 shard에 대해 query를 실행하면 , 해당 shard 안의 데이터에 대해서만 결과를 가져온다 / cluster level에서 query를 실행하고 싶다면, mongos 사용
    • 하나의 데이터베이스 안에 primary shard(shard 되지 않은 모든 collection 저장) 는 반드시 존재
  • mongos(=routers): cache the cluster metadata and act as a query router, providing an interface between client applications and the sharded cluster.
    • 클러스터 메타데이터를 캐시화하고, 클라이언트 어플리케이션과 Sharded 클러스터간의 인터페이스를 쿼리라우터 역할로서 제공한다.
    • 적절한 shard 로 route 하기 위해 config server로부터 metadata를 캐싱 
    • 각각의 shrad에 대해 query 를 분산시키기 위해 mongos라는 instance를 제공 
    • 어떠한 data나 설정 정보를 저장하지 않는다.
    • mongos 서버를 통해 데이터를 읽고, 쓰고 / config 서버의 metadata를 캐시 / 빅데이터를 샤드 서버로 분산하는 프로세스
  • config servers: store metadata persistently and configuration settings for the cluster
    • 클러스터에 대한 메타데이터 및 구성 설정을 영구 저장
    • 모든 shard에 대해 어떤 chunk를 들고 있는지 정보를 가지고 있고, 해당 metadata를 mongos에서 활용하여 query를 route한다.
    • 클러스터 설정 저장하는 server
    • config server로부터 data를 동기화 한다 
    • 샤드 서버의 인덱스 찾는데 필요/ 샤드 시스템에 대한 메타 데이터 저장 , 관리 역할
  • 샤드 키 (shard keys)
    • used to distribute the collection‟s documents across shards
    • 클러스터들의 샤드들 간에 collection의 document를 어떻게 분산할 것인가 결정
    • consists of a field or fields that exist in every document in the target collection
    • 대상 집합의 모든 document에 존재하는 필드로 구성
    • 컬렉션을 샤딩할 때, 샤드 키 선택 / 샤딩 후에는 변경 불가 
    • 여러 개의 shard 서버로 분할된 기준 필드 가르킴
    • partition 과 load balancing 의 기준, mongodb 데이터 저장과 성능에 절대적인 영향
  • 청크(chunks)
    • a contiguous range of shard key values within a particular shard 
    • 특졍 샤드 내의 연속적인 샤드 키 값 범위
    • each chunk has an inclusive lower and exclusive upper range based on the shard key. 
    • 각 청크에는 샤드 키를 기반으로 하는 포괄적인 하한 범위와 배타적인 상위 범위가 존재한다.
    • default size : 64 MB
    • 일정한 데이터양에 도달했을 때, 서버로 분할하는 단위
  • balancer and even chunk distribution
    • to achieve an even distribution of chunks across all shards in the cluster, a balancer runs in the background to migrate chunks across the shards when a shard contains too many chunks of a collection relative to other shards
    • 클러스터의 모든 파편에 걸쳐 고르게 분포하기 위해 , 샤드에 다른 파편에 비해 너무 많은 컬렉션 덩어리가 포함되어 있을 때, 밸런서가 백그라운드에서 실행되어 파편에 걸쳐 청크를 마이그레이션(데이터의 이동, 서버에 균등하게 데이터를 재조정하는 과정) 한다.

3. Sharding 의 이점

읽기 및 쓰기 (Reads / Writes)

           – read and write workloads can be scaled horizontally across the shards in the cluster by adding more shards.

           – for queries that include the shard key or the prefix of a compound shard key, mongos can target the query at a                     specific shard or set of shards

          – 샤드 클러스터의 샤드에 읽기 및 쓰기 워크로드를 분산시켜 각 샤드가 클러스터 작업의 서브 세트를 처리할 수 있도록

          –  더 많은 샤드를 추가하여 읽기 쓰기 워크로드를 클러스터 전체에 수평적으로 확장 할 수 있게.

• 저장 용량 (Storage Capacity)

          – each shard contains a subset of the total cluster data

          – as the data set grows, additional shards increase the storage capacity of the cluster.

          – 클러스터의 샤드에 데이터를 분산시켜 각 샤드가 전체 클러스터 데이터의 서브 세트를 포함.

          – 데이터 세트가 커짐에 따라 , 추가 샤드가 클러스터의 스토리지 용량을 증가 

고가용성 (High Availability)

           – a sharded cluster can continue to perform partial read / write operations even if one or more shards are                               unavailable 

          – in production

         – 클러스터는 한 개 이상의 shard를 사용할 수 없는 경우에도 부분 읽기 / 쓰기 작업을 계속 수행할 수 있음.

 

» 각 shard는 복제 세트로 구성 » config server는 최소 3개의 노드들로 구성된 복제 세트로 구성

 

4. Sharded and Non-Sharded Collections(샤드 및 비샤드 컬렉션)

• A database can have a mixture of sharded and unsharded collections

   - 데이터베이스에 샤드와 비샤드 컬렉션이 혼합되어 있을 수 있음

• Sharded collections are partitioned and distributed across the shards in the cluster. Unsharded collections are stored on a primary shard

   - 샤드 컬렉션이 샤드 컬렉션 안에서 분할과 분포되어있으면, 비샤드 컬렉션이 primary 샤드에 저장된다. 

샤드 및 비샤드 컬렉션

5. Connecting to a Sharded Cluster(샤드 클러스트에 연결)

     • you must connect to a mongos router to interact with any collection in the sharded cluster

     - 샤드 클러스터의 컬렉션과 상호작용하려면 mongos 라우터에 연결해야한다.

     • you can connect to a mongos via the mongo shell or a MongoDB driver

     - mongos를 사용하여 몽고쉘이나 몽고드라이버와 연결. 

mongos를 사용하여 샤드클러스터에 연결

6.  Two Sharding Strategies for distributing data across sharded clusters(샤드 클러스트에 데이터 배포하는 두가지 샤드 전략)

   1) Ranged sharding(범위 샤딩)

     • dividing data into several ranges based on the shard key values(샤드 키 값을 기준으로 데이터를 여러 범위로 구분)

     • Each chunk is then assigned a range based on the shard key values (각 청크에는 샤드 키 기초한 범위가 할당)

     • A range of shard keys whose values are “close” are more likely to reside on the same chunk 

        (값이 닫힘인 다양한 샤드 키가 동일한 청크에 더 많이 상주할 수 있음)

     • The efficiency of ranged sharding depends on the shard key chosen(선택한 샤드키에 따라 범위 내 샤딩 효율성이 달라짐)

Ranged sharding

   2)Hashed Sharding(해시 샤딩)

     • computing a hash of the shard key field‟s value(샤드 키 필드 값의 해시 계산)

     • Each chunk is then assigned a range based on the hashed shard key values.
       (각 청크에는 해시된 샤드 키 값에 기초한 범위가 할당)

     • While a range of shard keys may be “close”, their hashed values are unlikely to be on the same chunk.

        Data distribution based on hashed values facilitates more even data distribution, especially in data sets where

        the shard key changes monotonically

         (다양한 샤드 키가 닫힘 일 수 있지만, 해시된 값은 동일한 청크 위에 있지 않는다 / 해시된 값에 기반한 데이터 배포를 통해 특히,

          샤드 키가 단조롭게 변경되는 데이터 세트에서의 데이터 배포를 더욱 원활하게 수행)

Hashed Sharding

7. setting up a local test

      -> router(mongos) 1 + config server(mongod/ replica set 구성 필수) 1 + shard(mongod / replica set 구성 필수) 2

 

setting up a local test

[1단계] 6개 노드에 대한 데이터 폴더 생성

• c:\data\configdb1 와 c:\data\configdb2

• c:\data\shard1a 와 c:\data\shard1b

• c:\data\shard2a 와 c:\data\shard2b 

 

[2단계] config server 실행 및 복제 세트 구성

#1 ->  c:\> mongod -–configsvr -–port 27500 -–dbpath c:\data\configdb1 --replSet crs
#2 ->  c:\> mongod -–configsvr -–port 27501 -–dbpath c:\data\configdb2 --replSet crs 
#3 ->  c:\> mongo -–port 27500 
           > conf = {_id:”crs”, members:[{_id:0, host:”localhost:27500”},
           {_id:1, host:”localhost:27501”}]}
             > rs.initiate(conf) // 복제 세트 초기화
             . . . .
           crs:SECONDARY>
           crs:PRIMARY>

 

[3단계] router(mongos) 실행

#4  -> c:\> mongos -–port 27100 –-configdb crs/localhost:27500 

[4단계] shard #1 인스턴스 실행 및 복제 세트 구성

#5 ->  c:\> mongod -–shardsvr -–port 27200 -–dbpath c:\data\shard1a --replSet srs1 
#6  -> c:\> mongod -–shardsvr -–port 27201 -–dbpath c:\data\shard1b --replSet srs1
#7 ->  c:\> mongo -–port 27200  
           > conf = {_id:”srs1”, members:[{_id:0, host:”localhost:27200”},
           {_id:1, host:”localhost:27201”}]}
             > rs.initiate(conf) // 복제 세트 초기화 
             . . . . 
          srs1:SECONDARY> 
          srs1:PRIMARY>

[5단계] shard #2 인스턴스 실행 및 복제 세트 구성

#8 ->  c:\> mongod -–shardsvr -–port 27300 -–dbpath c:\data\shard1a --replSet srs2
#9  -> c:\> mongod -–shardsvr -–port 27301 -–dbpath c:\data\shard1b --replSet srs2
#10 ->  c:\> mongo -–port 27300  
           > conf = {_id:”srs2”, members:[{_id:0, host:”localhost:27300”},
           {_id:1, host:”localhost:27301”}]}
             > rs.initiate(conf) // 복제 세트 초기화 
             . . . . 
          srs2:SECONDARY> 
          srs2:PRIMARY>

 

[6단계] shard #1과 shard #2를 shard cluster에 추가

• mongos에 연결 후 runCommand 명령으로 shard #1 & #2를 추가

• shard 추가 및 데이터 sharding은 db가 admin일 때만 가능

#11 -> c:\> mongo –-host localhost -–port 27100 . . .
mongos> use admin
mongos> db.runCommand({addShard:”srs1/localhost:27200, localhost:27201”, allowLocal:true})
mongos>
mongos> db.runCommand({addShard:”srs2/localhost:27300, localhost:27301”, allowLocal:true})
mongos>
mongos> sh.status()

[7단계] sharding 할 데이터 생성

#11 ->  mongos>
mongos> use myshdb2
mongos> db.mycol.insert({“name”:“kim”, “year”:“1”})
mongos> . . . // 추가 삽입 n회
mongos> db.mycol.find().pretty()
mongos> 

[8단계] 데이터 sharding 활성화

#11 -> mongos> use admin // 다시 admin db 선택
mongos> db.runCommand({“enablesharding”:“myshdb2”})

[9단계] 데이터 sharding

• 컬렉션 수준에서 sharding

• 여기서 shard key는 _id 필드로 지정

#11 -> mongos> db.runCommand({“shardcollection”:“myshdb2.mycol”, “key”:{“_id”:1}})

 

 

반응형
반응형

1. Replication(복제)

    => 어떤 기억 장소에서, 데이터를 원형대로 읽어 내어 그 데이터를 동일한 물리적 형식으로 다른 기억 장소에 써 넣는 것

    => 데이터를 여러 db 서버에 분산하여 저장 관리하는 기술

   => 여러 벌의 동일한 데이터베이스를 운영하기위해 필요한 작업

   => 필요에 따라 클라이언트가 메인 서버가 아닌, 복제 서버에 READ 요청을 하도록 설정
         / 메인 서버 부하를 낮추고, 복제된 데이터를 다른 부가적 용도(리포팅, 백업 용도, 재해 복구)로 사용

 

- 왜 복제를 사용하나?

  • To keep your data safe
    • 데이터 안전하게 보관
  • High (24*7) availability of data
    • 24시간 데이터 사용 가능 
  • Disaster recovery
    • 재해 복구
  • No downtime for maintenance (like backups, index rebuilds, compaction)
    • 유지 보수를 위한 다운타임 없음(백업, 인덱스 재구성, 압축)
  • Read scaling (extra copies to read from)
    • 읽기 확장
  • Replica set is transparent to the application
    • 애플리케이션에 레플리카 세트가 투명함

 

-the process of synchronizing data across multiple servers

-provides redundancy and increases data availability with multiple copies of data on different database servers

-protects a database from the loss of a single server. 

   =>fault tolerance

-allows you to recover from hardware failure and service interruptions.

 

몽고디비에서 Replica set 사용

  • Replica set is a group of two or more nodes (generally minimum 3 nodes are required).

    • 2개 이상의 노드로 이루어진 그룹(최소 3개 노드 필요)
  • In a replica set, one node is primary node and remaining nodes are secondary.

    • 한 노드는 기본 노드 , 나머지 노드는 보조 노드
  • All data replicates from primary to secondary node.

    • 모든 데이터는 기본 노드에서 보조 노드로 복제
  • At the time of automatic failover or maintenance, election establishes for primary and a new primary node is elected.

    • 자동 failover또는 유지 보수 시, 기본 노드에 대한 선택이 설정되고, 새로운 기본 노드가 선택
  • After the recovery of failed node, it again join the replica set and works as a secondary node.

    • 실패한 노드를 복구한 후 , 다시 복제본 세트로 들어가 보조 노드로 작동

\

  • replica set(복제 세트)
    • mongoDB에서 사용되는 복제 기술(과거 : 마스터 슬레이브)
    • 같은 데이터를 저장하고, 백업하기 위해 여러 대의 DB 서버가 운영되고, 각각의 서버에 유지하는 복수개의 Mongodb
      인스턴스가 모인 추상적인 그룹
    • 주 노드 1개 / 보조 노드 복수개 사용 가능 
    • A group of mongod instances that maintain the same data set
    • 구성 
      • nodes with data
        1. ONE PRIMARY NODE(DB를 공유시킬 서버(메인)):주노드
          • receives and does all write operations
          •  records all changes to its data sets in its operation log, i.e. oplog (capped collection)
          • 클라이언트 앱들의 쓰기 / 읽기 요청을 모두 받음 . 변화된 모든 내용을 운영 로그 (oplog)에 남김
        2. Secondary nodes(공유되는 DB받을서버(복제 / 백업 공간(여러대 가능)):보조노드
          • apply operations asynchronously using oplog from the primary so that they have the same data set
          • oplog에 기록된 내용들을 동일하게 연산하여 주 노드와 항상 같은 데이터 유지 
      • a node without data(optional)
        1. an arbiter node(PRIMARY / SECONDARY 서버를 모니터링 해주는 역할(끊어지는지 확인 가능)):결정권자
          • 결정권 자는 주 노드의 데이터를 복제하지 않는다 
          • 데이터가 없기 때문에, 주 노드가 될 수 없다
          • 역할 : heartbeat를 통해 노드의 상태를 확인하고 , 유사 시 선거에만 참가

arbiter(결정권자)

 

기본적인 Replica Set 구성

2.  주 노드의 교체 

   => 주 노드와 보조 노드 사이에 주기적으로 주고 받는 heartbeat(=ping/ 2s) 신호 통해 주 노드가 정상적이지 않은 상황 발견하면, 
        나머지 보조 노드들의 선거(election)을 통해 새로운 주 노드를 선발 
   => 원래 주 노드가 정상 상태로 돌아오면, 다시금 주 노드의 역할 맡게 된다 

   => replicate the primary’s oplog and apply the operations to their data sets such that the secondaries’ data sets reflect the primary’s data set

   =>  Replica set members send heartbeats (pings) to each other every 2 seconds. If a heartbeat does not return within 10 seconds, the other members mark the member as inaccessible.

  • 주 노드 서버가 정상인 경우

주 노드 서버 정상

 

  • 주 노드 서버가 정상 작동하지 않는 경우(primary node 대체 : automatic failover)

주 노드 서버가 정상 작동하지 않음

- 보조 노드들은 자신들의 상태, 미리 지정한 Priority  값을 판단하여 어떤 보조 노드가 주 노드로 승격될 것인지 선거

- 만약, 점수가 동일하게 나오면 가장 최근에 반영된 데이터를 반영한 보조 노드가 승격 대상

- 선거가 끝나기 전 까지 Read 수행은 보조 노드를 통해 가능하게 미리 설정(선거 시간 10초 넘기지 않는다)가능,
    Write는 주 노드가 없는 상태이므로 불가능

- 주 노드가 정상 상황 아닌 경우 실패한 write 연산을 retry 하는 기능 있음 

-  If the primary is unavailable, an eligible secondary will hold an election to elect itself the new primary node
    (기본 선거 시간 : 10초)

- The replica set cannot process write operations until the election completes successfully

- The replica set can continue to serve read queries if such queries are configured to run on secondaries while the primary is offline

 

 

3. Read 연산(read preference)

read preference

- 기본적, 응용 프로그램은 읽기 작업을 복제세트의 기본 구성원으로 보냄

   그러나, 클라이언트는 읽기 기본 설정을 지정하여 읽기 작업을 보조로 보낼 수 있다.

- secondary 에 대한 비동기식 복제는 secondary가 primary data 상태를 반영하지 않은 data를 반환한다

- By default, clients read from the primary;
   however, clients can specify a read preference to send read operations to secondaries.

- Asynchronous replication to secondaries means that reads from secondaries may return data that does not reflect the    state of the data on the primary.

 

4. 여러 데이터 센터에 Replica Set 분산

  • 복수의 데이터 센터에 멤버들을 어떻게 분산?
    • 각 DB 노드들을 데이터 센터 분산에서는 멤버(member)로 호칭
    • 데이터 센터의 수를 홀수로 하면, 선거에서 동점이 나올 확률 줄일 수 있다.
    • 각 데이터 센터에는 최소한 1개의 멤버를 배포하는 것이 원칙
    • 주로 서비스를 수행할 데이터 센터와, 대체 운영 및 백업의 목적인 데이터 센터를 결정
    • 주 노드를 뽑는 선거는 모든 멤버 50% 이상의 과반수 득표를 해야 함
    • 과반수의 멤버를 특정 데이터 센터에 분산

 

- EX ) Replica Set 멤버가 5인 경우

Case 1) 2개의 데이터 센터

3개의 멤버는 데이터 센터 1에, 2개의 나머지 2개의 멤버는 데이터 센터 2에 분산한다.

- 만약 데이터 센터 1에 문제가 발생하면, replica set은 READ ONLY가 된다.

- 만약 데이터 센터 2에 문제가 발생하면, 데이터 센터 1의 멤버들의 수는 여전히 과반수가 넘으므로,

   replica set은 WRITE가 가능하다.

Case 2) 3개의 데이터 센터

2개의 멤버는 데이터 센터 1에, 2개의 나머지 2개의 멤버는 데이터 센터 2에, 1개의 멤버는 데이터 센터 3에 배포.

- 만약 어떤 데이터 센터에 문제가 발생하더라도, 나머지 데이터 센터의 멤버들이 선거가 가능한 상황이므로,
   replica set은 WRITE가 가능하다.

 

어느 데이터 센터가 문제가 생기더라도 주 노드의 유지가 가능한 멤버 분포
각 복제 멤버의 우선 순위 설정값을 통해, 주 노드로의 승격 가능성 조정

데이터 센터 수가 많을 수록 멤버들은 고루 분포되기 때문에, 선거 때 동점이 발생할 수 있고, 관리자가 사전에 특정 데이터 센터 내의 멤버들이 선거에서 주 노드로 선택될 확률을 더 많이 주고 싶을 수 있다.

   => 각 멤버 속성을 정의할 때, Priority  값을 미리 정의하여 조정할 수 있다.

 

- EX) Replica Set 멤버가 3인 경우

Case 1) 2개의 데이터 센터

두 개의 멤버는 데이터 센터 1에, 나머지 하나의 멤버는 데이터 센터 2에 둔다. 만약 결정권자(arbiter)를 둔다면, 멤버의 수가 더 많은 데이터 센터 1에 운영한다.

- 데이터 센터 1에 문제가 발생하면, 과반수의 멤버가 불능이 되어, 선거를 할 수 없는 상황이다. 데이터 센터 1이 정상적인 상태로 돌아올 때까지 replica set 자체는 READ ONLY 상태가 된다.

- 데이터 센터 2에 문제가 발생하면, 데이터 센터 1의 멤버들은 과반수이고 선거를 할 수 있으므로, 새로운 주 노드를 선임하여, replica set은 여전히 WRITE가 가능하다.

위와 같이, 데이터 센터 2개의 경우, WRITE가 불가능한 상황이 발생할 수 있기 때문에, 데이터 센터의 수는 최소 3개 이상으로 하는 것이 안전하다.

Case 2) 3개의 데이터 센터

각각의 데이터 센터에는 멤버가 1개씩 존재하는 구조가 된다.

- 데이터 센터 1,2, 3 어디든 문제가 발생하면, 나머지 2개의 멤버들은 선거를 통해 새로운 주 노드를 찾을 것이고, replica set은 여전히 WRITE가 가능하다.

Case 3) 5개의 데이터 센터

각각의 데이터 센터에는 멤버가 1개씩 존재하는 구조가 된다.

replica set 멤버 3 / 활용 연습 도식화

[1단계] 3개 멤버 노드에 대한 데이터 폴더 생성

• c:\data\node1

• c:\data\node2

• c:\data\arbiter

 

[2단계] 3개의 명령창에서 mongod 인스턴스를 각각 실행

• replSet 옵션 : 복제 세트 이름 지정

• bind_ip_all 옵션 : 3대의 컴퓨터 사용시 (local 연습 시에는 불필요)

#1 => c:\> mongod -–port 27111 -–dbpath c:\data\node1 -–replSet myrs -–oplogSize 256

#2  => c:\> mongod -–port 27112 -–dbpath c:\data\node2 -–replSet myrs -–oplogSize 256

#3  => c:\> mongod -–port 27113 -–dbpath c:\data\arbiter -–replSet myrs -–oplogSize 256

 

[3단계] 4번째 명령창에 mongo 쉘로 첫 번째 인스턴스에 접속

#4  => c:\> mongo -–port 27111 . . . >

 

[4단계] 4번째 명령창에서 Replica set 환경 설정 문서를 변수 conf에 저장(여기서, 첫 번째 인스턴스만 멤버로 설정)

#4  => > conf = {_id:”myrs”, members:[{_id:0, host:”localhost:27111”}]} //실제 IP 입력

 

[5단계] 4번째 명령창에서 Replica Set 초기화

#4 = > > rs.initiate(conf) // 복제 세트 초기화

                 . . . .

                 myrs:SECONDARY>

                myrs:PRIMARY>

 

• 출력된 실행 결과 (“ok”:1) 메시지 확인

• 잠시 대기 후 프롬프트 기호 변화 확인

 ->  27111 포트에서 수행 중인 mongod 인스턴스가 프라이머리 노드가 됨

 

[6단계] 4번째 명령창에서 나머지 두 인스턴스를 Replica Set에 추가 후 프롬포트 기호 변경 및 복제 상태 확인(brief summary)

#4  => myrs:PRIMARY> rs.add(“localhost:27112”)

             myrs:PRIMARY> rs.add(“localhost:27113”, {arbiterOnly:true}) 또는

                                             rs.addArb(“localhost:27113”)

            myrs:PRIMARY>

            myrs:PRIMARY> db.isMaster() // 상세 정보 보기는 rs.status() 사용

 

[7단계] 5 또는 6 번째 명령창에 mongo 쉘로 위 인스턴스 중 하나에 접속하여 세컨터리 및 아비터 노드임 확인

#5 => c:\> mongo -–port 27112

            . . .

            myrs:SECONDARY>

 

#6 =>  c:\> mongo -–port 27113

            . . .

           myrs:ARBITER>

 

• 프롬프트 기호 확인(세컨더리 멤버, 아비터 멤버)

[8단계] 4 또는 5번째 명령창에서 Replica Set 용 db 및 컬렉션 확인

# 4 => myrs:PRIMARY> use local // Replica Set 용 db 선택

             myrs:PRIMARY> db.getCollectionNames() // 또는 show Collections

 

[9단계] 4 또는 5번째 명령창에서 Replica Set 멤버 및 멤버 정보 확인

#4 => myrs:PRIMARY> db.system.replset.find().pretty()

 

[10단계] 4 또는 5번째 명령창에서 Replica Set 상태 자세히 확인

#4  => myrs:PRIMARY> rs.status()

 

[11단계] 4번째 명령창 (프라이머리 멤버) 에서 문서 삽입

#4  => myrs:PRIMARY> use sample

              myrs:PRIMARY> db.col.insert({uname:”kim”, age:19})

              myrs:PRIMARY> db.col.find().pretty() 

 

[12단계] 5번째 명령창(세컨더리 멤버) 에서 문서 검색

#5  => myrs:SECONDAY> rs.status()

             myrs:SECONDAY> rs.slaveOk() // 세컨더리 노드에서도 검색 허용

             myrs:SECONDAY> use sample

             myrs:SECONDAY> show collections

             myrs:SECONDAY> db.col.find().pretty()

 

[13단계] 4번째 명령창에서 프라이머리 mongod 멤버 셧다운

• 2 및 3번째 명령창(나머지 두 인스턴스 실행 중)에 출력되는 메시지 확인

#4  => myrs:PRIMARY> use admin

             myrs:PRIMARY> db.shutdownServer()

              . . .

             c:>

 

[14단계] 5번째 명령창(세컨더리 멤버)에서 멤버 상태 재확인

• 이전 프라이머리 및 새로운 프라이머리 확인

#5 => myrs:SECONDAY> rs.status()

           . . .

          myrs:PRIMARY> // 프롬프트 기호가 변화된 것에 주목

 

[15단계]5 번째 명령창(새로운 프라이머리)에서 새로운 문서 삽입

#5 => myrs:PRIMARY> db.col.insert({uname:”cho”, age:23})

           myrs:PRIMARY> db.col.find().pretty() 

 

[16단계] 1번째 창에서 명령창에서 첫 번째 mongod 인스턴스 재실행

#1  => c:\> mongod -–port 27111 -–dbpath c:\data\node1 -–replSet myrs -–oplogSize 256

 

[17단계] 4번째 창에서 mongod 쉘로 위 첫번째 인스턴스에 재접속

#4  => c:\> mongo -–port 27111

              . . .

              myrs:SECONDARY> // 프롬프트 기호 변화 주목

              myrs:SECONDARY> rs.status()

              myrs:SECONDARY> rs.slaveOk()

              myrs:SECONDARY> use sample

              myrs:SECONDARY> show collections

              myrs:SECONDARY> db.col.find().pretty()

 

[17단계] 4 -> 6 -> 5번째 명령창 (mongo쉘) 에서 각 mongod 인스턴스 셧다운

#4   => myrs:SECONDARY> use admin

              myrs:SECONDARY> db.shutdownServer()

              . . .

              > exit

 

#6    => myrs:ARBITER> use admin

               myrs:ARBITER> db.shutdownServer()

                . . .

                > exit

 

#5    => myrs:PRIMARY> myrs:SECONDARY> // 프롬프트 기호 변화 주목

               myrs:SECONDARY> use admin

               myrs:SECONDARY> db.shutdownServer()

              . . .

               > exit

반응형
반응형

1. MongoDB와 JAVA 연동

 

- mongod 인스턴스 및 데이터베이스 연결

// import된 각 패키지들에 대한 설명은 API 문서 참조
import com.mongodb.client.MongoDatabase;
import com.mongodb.MongoClient;
public class ConnectToDB {
   public static void main( String args[] ) {

   // Creating a Mongo client
   MongoClient myclient = new MongoClient("localhost" , 27017);

   // 또는 MongoClient myclient = new MongoClient();
   System.out.println("Connected to the database successfully");

   // Accessing the database (db가 없으면 새로 생성)
   MongoDatabase mydb = myclient.getDatabase("sdb");
  }
}

- 컬렉션 생성

import com.mongodb.client.MongoDatabase;
import com.mongodb.MongoClient;
public class ConnectToDB {
   public static void main( String args[] ) {
   
   // Creating a Mongo client
   MongoClient myclient = new MongoClient();
   System.out.println("Connected to the database successfully");
   
   // Accessing the database
   MongoDatabase mydb = myclient.getDatabase("sdb");
   
   //Creating a collection
   mydb.createCollection("sampleCol");
   System.out.println("Collection created successfully");
  }
}

- 특정 DB 내의 모든 컬렉션 이름 출력

import com.mongodb.client.MongoDatabase;
import com.mongodb.MongoClient;
. . .
public class ListOfCollection {
 public static void main( String args[] ) {
 . . .

 // Accessing the database
 MongoDatabase mydb = myclient.getDatabase("sdb");
 
 // listing all collections
   for (String name : mydb.listCollectionNames()) {
   System.out.println(name);
   }
 }
}

- 컬렉션 선택(반환)

import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.MongoClient;
import org.bson.Document;
public class selectingCollection {
  public static void main( String args[] ) {
   . . .

   // Accessing the database
   MongoDatabase mydb = myclient.getDatabase("sdb");

   // Retrieving a collection
   MongoCollection<Document> mycol = mydb.getCollection("sampleCol");
   System.out.println("Collection Col selected successfully");
  }
}

-컬렉션 제거(drop)

import com.mongodb.client.MongoCollection;
. . .
public class DroppingCollection {
 public static void main( String args[] ) {
 . . .
 // Accessing the database
 MongoDatabase mydb = myclient.getDatabase("sdb");
 
 // Retrieving a collection
 MongoCollection<Document> mycol = mydb.getCollection("sampleCol");
 
 // Dropping a Collection
 mycol.drop();
 System.out.println("Collection dropped successfully");
 }
}

- document삽입

. . .
import org.bson.Document;
public class insertingDocument {
 public static void main( String args[] ) {
 . . .
 // Retieving a collection
 MongoCollection<Document> mycol = mydb.getCollection("sampleCol");
 System.out.println("Collection Col selected successfully");
 
 // bson Document 객체 생성
 Document mydoc = new Document("title", "MongoDB")
 .append("id", 1)
 .append("description", "database")
 .append("likes", 100)
 .append("url", "http://www.tutorialspoint.com/mongodb/")
 .append("by", "tutorials point");
 mycol.insertOne(mydoc);
 System.out.println("Document inserted successfully");
 }
}

-컬렉션 내 모든 문서 검색

import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import java.util.Iterator;
. . .
public class RetrievingAllDocuments {
 public static void main( String args[] ) {
 . . .
 // Retrieving a collection
 MongoCollection<Document> mycol = mydb.getCollection("sampleCol");

 // Getting the iterable object
 FindIterable<Document> iterDoc = mycol.find();
 
 // Getting the iterator
 Iterator it = iterDoc.iterator(); // iterator 반환
 int i = 1;
   while (it.hasNext()) {
   System.out.println(it.next());
   i++;
   }
 }
}

-document 수정

import com.mongodb.client.MongoCollection;
import com.mongodb.client.FindIterable;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
. . .
public class UpdatingDocuments {
 public static void main( String args[] ) {
 . . .
 // Updating a document
 mycol.updateOne(Filters.eq("id", 1), Updates.set("likes", 150));
 System.out.println("Document update successfully...");
 
 // Getting the iterable object
 FindIterable<Document> iterDoc = mycol.find();
 
 // Getting the iterator
 Iterator it = iterDoc.iterator(); // iterator 반환
 int i = 1;
   while (it.hasNext()) {
   System.out.println(it.next()); i++;
   }
 }
}

- document 삭제

import com.mongodb.client.MongoCollection;
import com.mongodb.client.FindIterable;
import com.mongodb.client.model.Filters;
. . .
public class DeletingDocuments {
 public static void main( String args[] ) {
 . . .
 // Deleting a document
 mycol.deleteOne(Filters.eq("id", 1)); // deleteMany() 메소드
 System.out.println("Document deleted successfully...");
 
 // Getting the iterable object
 FindIterable<Document> iterDoc = mycol.find();
 int i = 1;
 
 // Getting the iterator
 Iterator it = iterDoc.iterator(); // iterator 반환
   while (it.hasNext()) {
   System.out.println(it.next()); i++;
   }
 }
}

-조건에 맞는 특성 문서 검색

import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import java.util.Iterator;
. . .
public class RetrievingAllDocuments {
 public static void main( String args[] ) {
 . . .
 // Retrieving a collection
 MongoCollection<Document> mycol = mydb.getCollection("sampleCol");

 // Finding a document with find(Bson filter) method
 // and Getting the iterable object
 FindIterable<Document> iterDoc = mycol.find(검색조건); // 커서 반환
 //검색 조건 : find() / delete() / update()  조건 표현은 동일 
 //각종 메소드 활용 가능 
 . . .
 }
}

 

-----------------------------------------------------------------------------------------------------------------------------------

자바 연동 과제는 따로 보관 ㅎㅎ

반응형
반응형

1. Aggregation(집계)

  • 집계 연산 : group values from multiple documents together, and perform a variety of operations on the grouped data to return a single result
  • 집계 작업은 데이터 레코드를 처리하고 계산 된 결과를 반환
  • 집계 작업은 여러 문서의 값을 함께 그룹화하고 그룹화 된 데이터에 대해 다양한 작업을 수행하여 단일 결과를 반환 할 수 있다.
  • 3가지 유형의 집계 연산 기능 제공
    • 집계 파이프라인
    • 맵-리듀스 함수
    • 단순 목적 집계 메소드

Aggregation 프레임워크

  • 집계 파이프라인
    • 여러 단계를 거쳐 최종 결과 산출
      • 각 단계 마다 다양한 파이프라인 작업 가능
        • ex) $project , $group , $match, $limit, $skip, $sort , 등 10개 연산자
      • 각 단계의 출력 결과가 다음 단계의 입력으로 제공
      • 문서를 여러 단계의 파이프 라인으로 처리해, 데이터를 처리/집계 한다고 이해
    • 집계 프레임워크에서 사용 문법
      • $project : 컬렉션에서 특정 필드를 선택하는데 사용
      • $match : 필터링 작업 / 다음 단계에 입력으로 제공되는 문서의 양 줄임
      • $group : 위에서 설명한 실제 집계 수행
      • $sort : 문서 정렬
      • $skip : 주어진 양의 문서에 대한 문서 목록에서 건너 뛸 수 있음
      • $limit : 현재 위치에서 시작하여 주어진 숫자로 볼 문서의 양 제한
      • $unwind : 배열을 사용하는 문서 되 감는데 사용 / 배열을 사용할 때는 데이터가 미리 결합 되어 있으며 , 이를 통해 작업을 취소하여 개별 문서를 다시 가질 수 있음 
        -> 다음 단계의 문서 양을 늘림
         
      • 정의 
db.컬렉션명.aggregate([<작업1>, . . . <작업n>])

db.mycol.aggregate([{$match:..}, {$group:..}, {$sort:..}])
//<작업n>은 문서 형식 {키 : 값} 으로 명세

mycol 컬렉션 -> $match 작업 -> $group 작업 -> $sort 작업 -> 출력 문서

 

1. 

2.

 

3. 최종

 

> db.mycol.aggregate([{$match:{by_user:“Neo4j”}}, { $unwind : “$tags”}, {$project:{“_id:0”, “title”:1, “tags”:1}} ])
{“title”:“Neo4j Overview”, “tags”:“neo4j”}
{“title”:“Neo4j Overview”, “tags”:“database”}
{“title”:“Neo4j Overview”, “tags”:“NoSQL”}

  • SQL과의 비교(SQL count(*) 에서 group by 는 mongodb 집계와 동일)
select $project, $group 함수($sum, $min, $avg 등)
from  aggregate()
join $unwind
where $match
group by $group
having $match

 

  • aggregation 표현식 목록
> db.mycol.aggregate([ {$group : { _id : "$by_user“ , num_tutorial : {$sum : 1} }} ])
//출력될 문서의 형식 { _id : 값1, num_tutorial : 값2 }
//$가 붙은 문자열 필드 값은 일반 문자열 값이 아닌 입력 문서의 특정 필드를 지정

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
    "result" : [
        
{
        
"_id" : "tutorials point",
        
"num_tutorial" : 2
        
},
       
{ "_id" : "Neo4j",
         "num_tutorial" : 1
         }
    
], "ok" : 1
}//각 사용자가 작성한 자습서 수 나타내는 목록
  • $sum 
    -> 각 그룹에 대해 그 그룹에 속하는 문서가 있을 때 마다 num_tutorial 필드 값을 1씩 증가
  • $avg
    -> 컬렉션의 모든 문서에서 제공된 모든 값의 평균 계산
  • $min 
    -> 컬렉션의 모든 문서에서 해당 값의 최소값 가져옴
  • $max
    -> 컬렉션의 모든 문서에서 해당 값의 최대값 가져옴
  • $push 
    -> 결과 문서의 배열에 값 삽입
  • $addToSet
    -> 결과 문서의 배열에 값을 삽입하지만 중복은 생성하지 않는다
  • $first
    -> 그룹화에 따라 소스 문서에서 첫 번째 문서를 가져옴 / 이전에 적용된 일부 "$sort" 단계와 만 의미 O
  • $last
    -> 그룹화에 따라 소스 문서에서 마지막 문서를 가져옴 / 이전에 적용된 일부 "$sort" 단계와 만 의미 O
반응형
반응형

쿼리문 예시 보기 좋은 사이트 입니다. 참고 ~

https://docs.mongodb.com/manual/tutorial/query-documents/
https://docs.mongodb.com/manual/reference/sql-comparison/

1. 중첩된 문서를 포함하는 문서에 대한 질의(embedded document 추가 예시)

> db.myCol.insert( { “name”: “kim”, “address”:{ “city”:“seoul”, “gu”:“nowon” }
  • 중첩된 문서 전체를 비교하는 질의
> db.myCol.find( {“address”:{“city”:“seoul”, “gu”:“nowon”} })
  • 중첩된 문서의 특정 필드 값 비교 질의
    • 필드 구분자로 '.' 을 사용
    • 반드시 ""로 묶어야 함
// partial match (중첩된 문서의 일부 필드만 일치 여부 비교)
> db.myCol.find( {“address.city”:“seoul”})
> db.myCol.find( {“address.gu”:”nowon”, “address.city”:“seoul”})
> db.myCol.find( {“address.gu”:”nowon”})
  • 배열을 포함하는 문서에 대한 질의1
> db.myCol.insertMany( [
{“name”: “cho”, “hobby”:[“football”, “swimming”]},
{“name”: “kim”, “hobby”:[“game”, “swimming”, “football”]}
])
  • 배열 전체 비교 질의

          - 완전 일치 

// exact match (배열 요소의 값, 개수, 순서까지 일치)
> db.myCol.find( {“hobby”:[“football”, “swimming”] })

       - 부분 일치(주어진 값들의 순서 상관 없이 배열 요소로 존재하는지 질의)

// partial match
> db.myCol.find( {“hobby”:{ $all:[“football”, “swimming”] } })
  • 배열 포함하는 문서에 대한 질의2
> db.myCol.insertMany( [
{ “name”: “joo”,
“hobby”:[“football”, “swimming”],
“points”:[25, 28, 30, 34] },
{“name”: “park”,
“hobby”:[“game”, “football”, “swimming”],
“points”:[27, 30, 40] }
])
  • 배열의 특정 요소(들)에 대한 질의
// 배열 hobby의 요소 값 중에 “swimming”을 내용으로 가지는 문서 검색
> db.myCol.find( {“hobby”:“swimming” })

// 배열 points의 요소 값 중에 하나라도 34보다 큰 값을 가지는 문서 검색
> db.myCol.find( {“points”:{$gt:34} })

// 배열 hobby의 두 번째 요소 값을 “swimming”으로 가지는 문서 검색
> db.myCol.find( {“hobby.1”:“swimming” })

// 크기가 3인 배열 hobby를 포함하는 문서 검색
> db.myCol.find( {“hobby”:{$size:3} })
  • 배열을 포함하는 문서에 대한 질의3
> db.myCol.insertMany( [
{ “name”: “joo”, “points”:[25, 27] },
{ “name”: “min”, “points”:[14, 21] },
{ “name”: “yoo”, “points”:[19] }
])
  • 배열 요소(들)에 대한 여러 개의 조건 가지는 질의
// 배열 points의 요소들 중에 (15보다 큰 조건만을 만족하는 요소도 있으면서 20보다 작은 조건을 만족하는 또 다른 요소도 있는 문서) 또는 (한 요소가 15보다 크면서 20보다 작은 조건을 모두 만족)하는 문서 검색
> db.myCol.find( {“points”:{$gt:15, $lt:20} })

// 배열 points의 요소들 중에 적어도 하나라도 (21보다 크고 26보다 작은 조건을 모두 만족)하는 요소를 가지는 문서 검색
> db.myCol.find( {“points”:{$elemMatch:{$gt:21, $lt:26}} })
  • 배열을 포함하는 문서에 대한 질의 4
    • 배열의 요소 값이 문서인 경우 질의 (심화 질의)
> db.myCol.insertMany( [
{ “name”:“cho”,“friends”:[{“name”:”ko”},{“name”:”joo”,“age”:24}] },
{ “name”:“yoo”,“friends”:[{“name”:”jon”, “age”:20},{“name”:”je”}] } ] )

Q1) 이름이 joo이고 나이가 24인 친구를 가지고 있는 사람의 이름은?
Q2) 나이가 22살 이하인 친구를 가지고 있는 사람의 이름은?
Q3) 첫 번째 친구의 나이가 20인 친구를 가지고 있는 사람의 이름은?

2. Indexing(인덱스)

  • 몽고 디비 쿼리에서 효율적인 실행을 지원
    -> 인덱싱이 없이 몽고디비는 콜렉션 스캔을 실행하여야 한다.
    -> ex) 쿼리문에 일치하는 도큐먼트 선별하기 위해 컬렉션 내의 모든 도큐먼트를 스캔해야한다
  • 인덱스 : 콜렉션의 데이터셋의 작은 일부를 저장하고 있는 특별한 데이터 구조
    -> 인덱스는 특정 필드 또는 필드 세트의 값을 인덱스에 지정된 필드 값 순서로 저장
    ->
    컬렉션내의 임의의 문서를 빠르게 접근하도록 하는 자료구조

    ->인덱스는 데이터 파일과는 별도의 파일에 저장됨
    ->검색 속도를 향상시키나 인덱스 저장 공갂 필요
    -> 삽입, 삭제, 수정 연산의 속도 저하
  • 인덱스의 구조
    -> 엔트리 구조 : < 탐색 키 필드, 문서에 대핚 포인터 >

    ->엔트리들은 탐색 키 필드 값의 오름차순으로 정렬되어 있음

 

  • 다단계 인덱스 : B, B+ 트리 사용

  1) ensureIndex() 메서드 

db.COLLECTION_NAME.ensureIndex({KEY : 1})

-> key 는 색인을 작성하려는 필드의 이름 / 1은 오름차순 / 내림차순으로 인덱스를 만들려면 -1

-> 여러 필드에 인덱스를 만들려면 여러 필드를 전달할 수 있다.

>db.mycol.ensureIndex({"title" : 1})
>db.mycol.ensureIndex({"title":1,"description":-1}) //여러 필드 전달
  • ensureIndex() 메소드는 옵션 목록도 허용합니다.
PARAMETER TYPE DESCRIPTION
background boolean 인덱스를 빌드해도 다른 DB 활동을 차단하지 않도록 백그라운드에서 인덱스를 빌드한다. 백그라운드에서 빌드하려면 TRUE / 기본값은 FALSE
unique boolean 인덱스 키가 인덱스의 기존 값과 일치하는 문서 삽입을 허용하지 않도록 고유 인덱스를 생성/ 고유 인덱스를 작성하려면 TRUE 지정 / 기본값은 FALSE
name string 인덱스의 이름/ 지정되지 않은 경우 mongodb는 인덱스화 된 필드의 이름과 정렬 순서를 연결하여 인덱스 이름을 생성
dropDups boolean 중복될 수 있는 필드에 고유 인덱스를 작성 / mongodb는 키의 첫번째 항목만 인덱스화하고 해당 키의 후속 항목이 포함된 콜렉션에서 모든 문서를 제거 / 고유 인덱스를 작성하려면 true를 지정/ 기본값은 false
sparse boolean true인 경우 인덱스는 지정된 필드가 있는 문서만 참조 / 이 인덱스는 공간을 덜 사용하지만 일부 상황(정렬..) 에서 다르게 동작 / 기본값 false
expireAfterSeconds Integer mongodb가 콜렉션에서 문서를 보유하는 기간을 제어하기 위해 TTL 값을 초 단위로 지정
v Index Version 색인 버전 번호 / 기본 인덱스 버전은 인덱스 작성시 실행중인 mongodb 버전에 따라 다름
weights Document 가중치는 1~99,999 범위의 숫자, 점수를 기준으로 다른 색인화 된 필드에 대한 필드의 중요성 나타냄
default_language string 텍스트 인덱스의 경우 중지 단어 목록과 형태소 분석기 및 토크 나이저에 대한 규칙을 결정하는 언어 / 기본값 english
language_override string 텍스트 인덱스의 경우 기본 언어를 대체 할 언어를 포함하는 문서의 필드 이름 지정 / 기본값은 언어

 

2. 커서(5주차 추가 메뉴얼)

  • 커서의 활용
    • find() 메소드 : 검색된 문서 집합에 대한 커서 반환
  • var 타입의 번수 사용하지 않는 경우
// mongo 쉘에서는 반환 결과를 변수에 할당하지 않으면
// 커서가 자동으로 20번 반복되어 문서 20개를 자동 출력 후 대기
// “it” 입력하면 커서 반복
> db.myCol.find()
  • var 타입의 변수 사용하는 경우
    • 반환된 문서 집합에 대해 커서를 수동으로 반복하여 개별적 문서 접근
> var myCursor = db.myCol.find()
> myCursor // 커서 20번 반복 -> 20개 문서 출력 후 대기
> var myCursor = db.myCol.find()
> while (myCursor.hasNext()) {
           print(tojson(myCursor.next()));
           // printjson(myCursor.next());
}
  • 커서 활용
    • 검색 결과의 문서 개수 출력
> db.myCol.find.count()
> var res = db.myCol.find.count()
> res

3. Index 메소드

인덱스 생성 메소드 //createIndex()

db.컬렉션명.createIndex(<키> , <옵션>)
// <키>는 문서 형식 {키:1 or -1, ... }으로 명세 (1:오름, -1:내림)
// <옵션>도 문서 형식 {키:값, ... }으로 명세
  • 단일 / 복합 인덱스 (single / compound index) 생성
db.mycol.createIndex({"age" : 1})
//단일 키 인덱스(하나의 필드만 사용)

db.mycol.createIndex({"deptname" : 1, "year" : -1})
//복합 키 인덱스 (2개 이상의 필드 사용)
//키의 순서 중요
  • 다중키 인덱스(multikey index)
    • 필드의 값이 배열(예, 취미)인 경우 생성되는 인덱스 (별도 지정 불필요)
    • 배열의 각 요소 마다 인덱스 엔트리 유지
      • 같은 배열에서 생성된 여러 엔트리들을 동일한 문서 참조(포인트)
  • 인덱스 생성시 인덱스명 작명
    • 시스템이 기본적으로 주는 기본 이름 대신 의미 있는 이름으로 작명
    • 기본 이름 : 인덱스 키 (필드) 와 정렬 기준(1 / -1) 값을 조합하여 작명
db.mycol.createIndex({username : 1} , {name : "userinfo_idx"})

 

  • 고유 인덱스 (unique index)
    • 컬렉션 내 동일한 인덱스 필드 값을 갖는 문서 중복 불가
    • _id 필드에 대한 고유 인덱스는 자동으로 생성
    • 문서 삽입 이전에 인덱스를 생성하는 것 좋음
db.mycol.createIndex({username : 1}, {unique : true})

 

  • 희소 인덱스(sparse index)
    • 인덱스 키 필드를 포함하는 문서에 대해서만 인덱스 엔트리를 유지
    • oop, 밀집 인덱스(dense index)
    • 모든 문서에 포함되지 않는 필드에 인덱스를 생성할 경우 유용
db.mycol.createIndex({fax : 1}, {sparse : true, unique : true})

 

인덱스 정보 확인 메소드 //getIndexes()

  • 한 컬렉션 내에 생성된 모든 인덱스 정보를 문서 배열로 반환
db.컬렉션명.getIndexes() 또는 db.컬렉션명.getIndexSpecs()

> db.mycol.getIndexes() [
  {
                “v”:1, // 인덱스 버전 번호 (미활용)
               “key”:{“username”:1}, // 인덱스 키 정보
               “ns”:“mycol.username”, // 네임 스페이스
               “name”:“username_1” // 인덱스명
   },
  { . . . }
]

 

인덱스 제거 메소드 //dropIndex()

  • 컬렉션 내의 특정 인덱스 제거
    • <인덱스_정보>  : 문서 형식으로 명세 : {"인덱스명" : 1 또는 -1}
db.컬렉션명.dropIndex("인덱스명" 또는 <인덱스_정보>)
> db.mycol.dropIndex(“stdinfo_idx”)
> db.mycol.dropIndex(“username_1”)
> db.mycol.dropIndex({“username”:1})

 

  • 여러 개의 인덱스 제거 메소드
    • 해당 컬렉션에 대한 모든 인덱스 제거 (단, _id 인덱스는 제외)
db.컬렉션명.dropIndexes()
반응형
반응형

Mongodb - Limit Records

-find() 메소드를 더욱 더 활용에 필요한 sort(), limit() , skip() 메소드

-find() 메소드를 사용했을 시  cursor 형태의 결과값을 반환, 이 객체가 가지고 있는 limit() , skip()메소드를 통해 보이는 출력물의 갯수를 제한, sort() 메소드를 사용하여 데이터를 순서대로 나열

 

1. limit() //db.콜렉션명.find().limit(number)

이 메소드는 출력할 데이터 갯수를 제한할 때 사용. value 파라미터는 출력 할 갯수 값

>db.mycol.find({}, {"title" : 1, _id:0}).limit(2)
  { "title" : "Mongodb"}
  { "title" : "Nosql"}

 

2. Skip() //db.콜렉션명.find().limit(number).skip(number)

출력 할 데이터의 시작부분을 설정할 때 사용.  value 값 갯수의 데이터를 생략하고 그 다음부터 출력

>db.mycol.find({}, {"title" : 1, _id : 0}).limit(1).skip(1)
  { "title" : "Mongodb"}

3.Sort() //db.콜렉션명.find().sort({key : 1})

이 메소드는 데이터를 정렬할 때 사용. 매개변수로는 어떤 KEY 를 사용하여 정렬 할 지 알려주는 document 를 전달

KEY 는 데이터의 field 이름이고, value 의 값은 1 혹은 -1 . 이 값을 1로 설정하면 오름차순으로, -1로 하면 내림차순으로 정렬

또한 여러 KEY를 입력 할 수 있고 먼저 입력한 KEY가 우선권을 가짐.

>db.mycol.find({}, "title" : 1, _id:0}).sort({"title" : -1}) //역순 출력

Mongodb 메뉴얼 (튜토리얼에는 없지만 중요하다)

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"} )

 

배열값 조회

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}} )

 

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" } } } )


조회 결과에서 필드 표시 여부

 

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 } )

 

Null 값과 필드 존재여부 조회

 

아래의 식은 item 필드가 null 인 값도 조회 하지만, item 필드가 존재하지 않는 문서도 조회가 됩니다.

db.inventory.find( { item: null } )

item 필드가 존재하지 않는 문서를 조회합니다.

db.inventory.find( { item : { $exists: false } } )

 

이름설명

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

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];
출처: https://cionman.tistory.com/48 [Suwoni블로그]
반응형
반응형

MongoDB - Query Document 

 

조회 (find()) //db.COLLECTION_NAME.find(query, projection)

Document 를 조회하는 find() 메소드

 

find() 메소드의 인자로 query 와 projection 이 들어옵니다.

두 값 모드 Optional 파라메터입니다.

query 의 데이터 타입은 document(객체) 입니다. 이는 다큐먼트를 조회하는 기준을 정하는 파라메터입니다. 이 값이 생략되거나 비어있는 객체 {} 를 전달하면 해당 컬렉션의 모든 다큐먼트들을 조회합니다.

projection 의 데이터 타입 역시 document 로, 조회한 다큐먼트의 표시할 field 를 지정하는 것 입니다.

 

실습 위해 컬렉션 만들어보고 삽입!

>db.articles.insert([

  {

    "title": "article01",

    "content": "content01",

    "writer": "Velopert",

    "likes": 0,

    "comments": []

  },

  {

    "title": "article02",

    "content": "content02",

    "writer": "Alpha",

    "likes": 23,

    "comments": [

      {

        "name": "Bravo",

        "message": "Hey Man!"

      }

    ]

  },

  {

    "title": "article03",

    "content": "content03",

    "writer": "Bravo",

    "likes": 40,

    "comments": [

      {

        "name": "Charlie",

        "message": "Hey Man!"

      },

      {

        "name": "Delta",

        "message": "Hey Man!"

      }

    ]

  }

])
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 3,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

db.articles.find().pretty()
{
        "_id" : ObjectId("5d80289f790e7a86104506af"),
        "title" : "article01",
        "content" : "content01",
        "writer" : "Velopert",
        "likes" : 0,
        "comments" : [ ]
}
{
        "_id" : ObjectId("5d80289f790e7a86104506b0"),
        "title" : "article02",
        "content" : "content02",
        "writer" : "Alpha",
        "likes" : 23,
        "comments" : [
                {
                        "name" : "Bravo",
                        "message" : "Hey Man!"
                }
        ]
}
{
        "_id" : ObjectId("5d80289f790e7a86104506b1"),
        "title" : "article03",
        "content" : "content03",
        "writer" : "Bravo",
        "likes" : 40,
        "comments" : [
                {
                        "name" : "Charlie",
                        "message" : "Hey Man!"
                },
                {
                        "name" : "Delta",
                        "message" : "Hey Man!"
                }
        ]
}
  • articles 의 다큐먼트 중 writer 가 Bravo 인 다큐먼트를 검색

특정 field 의 정확한 값으로 다큐먼트를 조회할 때는 find 의 query 로 찾을 document 를 객체 형식으로 지정

db.articles.find({ "writer" : "Bravo" }).pretty()
{
        "_id" : ObjectId("5d80289f790e7a86104506b1"),
        "title" : "article03",
        "content" : "content03",
        "writer" : "Bravo",
        "likes" : 40,
        "comments" : [
                {
                        "name" : "Charlie",
                        "message" : "Hey Man!"
                },
                {
                        "name" : "Delta",
                        "message" : "Hey Man!"
                }
        ]
}

 

Query 연산자

  • 비교 연산자

operator

 설명 

 $eq

 (equals) 주어진 값과 일치하는 값 

 $gt

 (greater than) 주어진 값보다 큰 값 

 $gte

 (greater than or equals) 주어진 값보다 크거나 같은 값 

 $lt

 (less than) 주어진 값보다 작은 값 

 $lte

 (less then or equals) 주어진 값보다 작거나 같은 값 

 $ne

 (not equlas) 주어진 값과 일치하지 않는 값 

 $in

 (in) 주어진 배열 안에 속하는 값

 $nin

 (not in) 주어진 배열 안에 속하지 않는 값 

 

articles 콜렉션 안의 다큐먼트 중 like 필드의 값이 10보다 크고 30보다 작은 다큐먼트를 조회

db.articles.find( { "likes" : { $gt : 10, $lt : 30 } } ).pretty()
{
        "_id" : ObjectId("5d80289f790e7a86104506b0"),
        "title" : "article02",
        "content" : "content02",
        "writer" : "Alpha",
        "likes" : 23,
        "comments" : [
                {
                        "name" : "Bravo",
                        "message" : "Hey Man!"
                }
        ]
}
  •  논리(Logical) 연산자

Operator 

 설명 

 $or

 주어진 조건 중 하나라도 만족한다면 true 

 $and

 주어진 조건을 모두 만족해야만 true 

 $not

 주어진 조건이 거짓일 때 true 

 $nor

 주어진 모든 조건이 거짓일 때 true 

-title 의 값이 "article01" 이거나 writer 의 값이 "Alpha" 인 도큐먼트를 조회

db.articles.find( { $or : [ { title : "article01" }, { writer : "Alpha" } ] } ).pretty()
{
        "_id" : ObjectId("5d80289f790e7a86104506af"),
        "title" : "article01",
        "content" : "content01",
        "writer" : "Velopert",
        "likes" : 0,
        "comments" : [ ]
}
{
        "_id" : ObjectId("5d80289f790e7a86104506b0"),
        "title" : "article02",
        "content" : "content02",
        "writer" : "Alpha",
        "likes" : 23,
        "comments" : [
                {
                        "name" : "Bravo",
                        "message" : "Hey Man!"
                }
        ]
}

-writer 의 값이 "Alpha" 이고, like 의 값이 20 이상인 다큐먼트를 조회

db.articles.find( { $and : [ { writer : "Alpha" }, { likes : { $gt : 20 } } ] } ).pretty()
{
        "_id" : ObjectId("5d80289f790e7a86104506b0"),
        "title" : "article02",
        "content" : "content02",
        "writer" : "Alpha",
        "likes" : 23,
        "comments" : [
                {
                        "name" : "Bravo",
                        "message" : "Hey Man!"
                }
        ]
}
>

 

-$and 연산자는 하나의 query 객체로 표현하는 것과 같음.

 

db.articles.find( { $and : [ { writer : "Alpha" }, { likes : { $gt : 20 } } ] } ).pretty()

=

db.articles.find( { writer : "Alpha", likes : { $gt : 20 } } ).pretty()

 

 

 

Update() //db.콜렉션명.update(SELECTION_CRITERIA, UPDATED_DATA)

>db.mycol.update({'title' : 'MONGO DB'}, {$set  :{'title' : 'new mongo'}})
>db.mycol.update({'title' : 'MONGO DB'}, {$set  :{'title' : 'new mongo'}}, {multi : true})

 

Save() //db.콜렉션명.save({_id : 객체id(), new_data})

save()는 동일 id값이 들어오면 update. 그리고 save() 함수 변경시 변경/추가 여부를 결과값으로 알려줌

> db.user.save({ "_id" : 5, "name" : "matt", "part" : "staf", "title" : "lab" })
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 5 })

 

> db.user.save({ "_id" : 5, "name" : "matt", "part" : "staff", "title" : "lab" })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.user.find()
{ "_id" : 5, "name" : "matt", "part" : "staff", "title" : "lab" }

 

Remove() //db.콜렉션명.remove(delete_creiteria)

>db.mycol.remove({'title' : 'mongo'})

 

Projection

일반적인 SQL 쿼리문에서 "select" 구문에 해당하는 Projection은 find() 메소드의 두번째 인자값에 해당.

/* sample query */ db.tbl.find( { num: { $gt: 29} }, { val1: 1, val2: 1 } ◀ projection ).limit(10)

 

위의 코드에서 "projection"으로 표시된 부분
만약 _id 필드를 projection에서 제외하면 추후에 projection을 합칠 때 문제가 생김.

위 구문에서 val1 필드 값인 1은 추출한 콜렉션에서 val1 필드를 포함하고 반대로 val1 필드 값이 0이라면 추출한 콜렉션에서 val1 필드를 제외. 따라서 위 구문은 val1과 val2 필드를 포함하겠다는 뜻.

 

 

1.추출할 콜렉션에서 특정 필드를 제외 쿼리 예시

db.t_col.find({ "view_count": { $gt: 29 }, { "title":0 })

 

위의 쿼리를 실행하면 view_count값이 29보다 큰 document들을 선택하고, 선택된 document들의 필드 중 "title" 필드를 제외.

 

2 .2개의 필드와 _id 필드를 포함하는 쿼리.

db.t_col.find({ "view_count": { $gt: 29 }, { "title":1, "cont":1 })

위의 쿼리를 실행하면 view_count값이 29보다 큰 document들을 선택하고, 선택된 document들의 필드 중 "title", "cont", "_id" 필드만 가져옴.

 

3. 2개의 필드를 포함하고 _id 필드를 제외하는 쿼리.

db.t_col.find({ "view_count": { $gt: 29 }, { "title":1, "cont":1, "_id":0 })

 

위의 쿼리를 실행하면 view_count값이 29보다 큰 document들을 선택하고, 선택된 document들의 필드 중 "_id"필드를 제외하고 "title", "cont" 필드만 가져옴

반응형

+ Recent posts