MongoDB 사용하기
MongoDB와 연결하기
어떤 플랫폼을 기반으로 사용할지 정해야한다. 많은 플랫폼을 지원하지만 Nodejs와 Python에 대해서만 다뤄보겠다.
Nodejs
Nodejs에서 제공하는 MongoDB 드라이버는 두 개이다.
MongoDB Client
MongoDB에서 제공하는 공식 드라이버이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| const { MongoClient, ServerApiVersion } = require("mongodb");
// Replace the placeholder with your Atlas connection string
const uri = "mongodb://<connection string>";
// Create a MongoClient with a MongoClientOptions object to set the Stable API version
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
}
}
);
async function run() {
try {
// Connect the client to the server (optional starting in v4.7)
await client.connect();
// Send a ping to confirm a successful connection
await client.db("admin").command({ ping: 1 });
console.log("Pinged your deployment. You successfully connected to MongoDB!");
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
}
run().catch(console.dir);
|
Mongoose
MongoDB에서 제공하는 공식 드라이버는 아니지만 점유율이 꽤나 높은 오픈소스 드라이버다. 내부적으로는 MongoDB에서 공식적으로 제공하는 드라이버를 사용하여 구현되었지만 공식 드라이버에서 제공되지 않는 여러 편의 기능들이 들어가 있다.
아래는 Mongoose에서 접속하는 코드에 대한 예시이다.
1
2
3
4
5
6
| const mongoose = require("mongoose")
const uri = 'mongodb://<connection string>';
mongoose.connect(uri, function(error) {
// if error is truthy, the initial connection failed.
})
|
Python
Python에서는 PyMongo 패키지를 이용하여 MongoDB에 접속한다. 접속하는 예시 코드는 아래와 같다.
1
2
| from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
|
지원하는 쿼리 형태
기본적인 CRUD 부터 살펴보고 차후에 고급 기능을 알아보도록 하겠다. 아래의 CRUD 명령어는 MongoShell에서 지원하는 명령어들이다. 종류는 훨씬 많지만 기본적인 것 두 개씩만 다뤄보겠다.
data라는 db에서 inventory라는 collection에 엑세스해서 작업 할때를 가장해서 예시코드를 작성하도록 하겠다.
1
2
3
4
5
6
| //mongoose
const schema = new Schema({
A:Number,
B:Number
});
const inventoryCol = mongoose.model('inventory', schema);
|
1
2
3
| # pymongo
data_db = client.data
data_inventory_col = data_db.inventory
|
Create
데이터 삽입시에 사용하는 쿼리이다.
insertOne
옵션 항목은 아래와 같다.
1
2
3
4
5
6
| db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
|
writeConcern : ReplicaSet일 경우에 어떤 쓰기 방식을 취할지인데 총 세 가지가 있다.
1
2
3
| majority : PSS에서 다수 개의 mongod에 쓰기 처리가 되어야 넘어감
<number> : 지정해둔 mongod 노드 수 만큼 처리가 되어야 넘어감
<custom write concern name> : 별도로 정의해둔 tag 값을 가진 노드 수 만큼 처리가 되어야 넘어감
|
각 드라이버 별 예시는 아래와 같다.
1
2
3
| // MongoDB Shell
// A 속성이 1인 도큐먼트 추가 (_id는 자동 포함)
db.inventory.insertOne( { "A":1 } )
|
1
2
3
| // Mongoose
// A 속성이 1인 도큐먼트 추가 (_id는 자동 포함)
await inventoryCol.insertOne( { "A":1 } )
|
1
2
3
| # Pymongo
# A 속성이 1인 도큐먼트 추가 (_id는 자동 포함)
data_inventory_col.insert_one({"A":1 })
|
insertMany
옵션 항목은 아래와 같다.
1
2
3
4
5
6
7
| db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
|
writeConcern : ReplicaSet일 경우에 어떤 쓰기 방식을 취할지인데 총 세 가지가 있다.
1
2
3
| majority : PSS에서 다수 개의 mongod에 쓰기 처리가 되어야 넘어감
<number> : 지정해둔 mongod 노드 수 만큼 처리가 되어야 넘어감
<custom write concern name> : 별도로 정의해둔 tag 값을 가진 노드 수 만큼 처리가 되어야 넘어감
|
ordered: 정렬된 삽입을 할 것인지 정렬되지 않은 삽입을 할것 인지 정할 수 있다. 기본값은 true이다.
각 드라이버 별 예시는 아래와 같다.
1
2
3
| // MongoDB Shell
// A 속성이 1인 도큐먼트 추가 (_id는 자동 포함)
db.inventory.insertMany( [{ "A":1 },{ "B":1 }] )
|
1
2
3
| // Mongoose
// A 속성이 1인 도큐먼트 추가 (_id는 자동 포함)
await inventoryCol.insertMany( [{ "A":1 },{ "B":1 }] )
|
1
2
3
| # Pymongo
# A 속성이 1인 도큐먼트 추가 (_id는 자동 포함)
data_inventory_col.insert_many([{"A": 1}, {"B": 1}])
|
Read
findOne
기본적으로 document를 찾을 때 query 형식은 아래와 같다.
1
| { <field1>: { <operator1>: <value1> }, ... }
|
찾고자 하는 필드 속성에 operator와 값이 붙는 방식인데 해당 operator에 들어갈 수 있는 것들의 몇 가지 예시는 아래와 같다.
1
2
3
4
5
| $or : n개 중 한 개라도 해당하면 반환
$and : n개 모두 다 해당해야 반환
$in : 해당 내용이 포함되어있으면 반환
$gte : 크거나 같으면 반환
$gle : 작거나 같으면 반환
|
이렇게 찾는 조건만이 아니라 필요한 값만 잘라올 수 도 있는데 query 조건 이후에 obj 형식으로 넘긴다. 해당 부분은 다음과 같다.
1
| { <field1>: <value1>, ... }
|
value에는 0또는 1이 들어갈 수 있는 1이면 해당 값을 갖고 오는 것, 0이면 해당 값을 갖고 오지 않는 것이다. 아예 이 부분을 생략 해버리면 전체 document를 갖고온다.
각 드라이버 별 예시는 아래와 같다.
1
2
3
4
5
| // MongoDB Shell
// A 속성이 1인 한 개의 도큐먼트를 갖고 온다.
db.inventory.findOne( { "A":1 } )
// A 속성이 0 이상인 도큐먼트를 한 개를 B 속성과 _id만 갖고 온다.
db.inventory.findOne({"A":{"$gte":0}},{"B":1})
|
1
2
3
4
5
| // Mongoose
// A 속성이 1인 한 개의 도큐먼트를 갖고 온다.
await inventoryCol.findOne( { "A":1 })
// A 속성이 0 이상인 도큐먼트를 한 개를 B 속성과 _id만 갖고 온다.
await inventoryCol.findOne({"A":{"$gte":0}},{"B":1})
|
1
2
3
4
5
| # Pymongo
# A 속성이 1인 한 개의 도큐먼트를 갖고 온다.
data_inventory_col.find_one({"A": 1})
# A 속성이 0 이상인 도큐먼트를 한 개를 B 속성과 _id만 갖고 온다.
data_inventory_col.find_one({"A": {"$gte": 0}}, {"B": 1})
|
find
기본적으로 document를 찾을 때 query 형식은 findOne과 같다.
1
| { <field1>: { <operator1>: <value1> }, ... }
|
찾고자 하는 필드 속성에 operator와 값이 붙는 방식인데 해당 operator에 들어갈 수 있는 것들의 몇 가지 예시는 아래와 같다.
1
2
3
4
5
| $or : n개 중 한 개라도 해당하면 반환
$and : n개 모두 다 해당해야 반환
$in : 해당 내용이 포함되어있으면 반환
$gte : 크거나 같으면 반환
$gle : 작거나 같으면 반환
|
이렇게 찾는 조건만이 아니라 필요한 값만 잘라올 수있는 project 기능도 있는데 query 조건 이후에 key:value 형식의 obj로 넘긴다. value에는 0또는 1이 들어갈 수 있는 1이면 해당 값을 갖고 오는 것, 0이면 해당 값을 갖고 오지 않는 것이다. 아예 이 부분을 생략 해버리면 전체 document를 갖고온다. 해당 부분은 다음과 같다.
1
| { <field1>: <value1>, ... }
|
정렬을 해서 갖고 올 수 도 있는데 이것은 일반적으로 find 함수에 체이닝해서 갖고 온다. 정렬하고 싶은 필드를 key로 두고 value를 1또는 -1로 두는데 1이면 오름차순 -1이면 내림차순으로 지정된다.
해당 세팅에 대한 예시는 아래와 같다.
1
| db.inventory.find().sort({"A":1})
|
각 드라이버 별 예시는 아래와 같다.
1
2
3
4
5
| // MongoDB Shell
// A 속성이 1인 모든 도큐먼트를 갖고 온다.
db.inventory.find( { "A":1 } )
// A 속성이 0 이상인 모든 도큐먼트의 B 속성과 _id만 갖고 온다.
db.inventory.find({"A":{"$gte":0}},{"B":1})
|
1
2
3
4
5
| // Mongoose
// A 속성이 1인 모든 도큐먼트를 갖고 온다.
await inventoryCol.find( { "A":1 } )
// A 속성이 0 이상인 모든 도큐먼트의 B 속성과 _id만 갖고 온다.
await inventoryCol.find({"A":{"$gte":0}},{"B":1})
|
1
2
3
4
5
| # Pymongo
# A 속성이 1인 모든 도큐먼트를 갖고 온다.
data_inventory_col.find({"A": 1})
# A 속성이 0 이상인 모든 도큐먼트의 B 속성과 _id만 갖고 온다.
data_inventory_col.find({"A":{"$gte":0}},{"B":1})
|
Update
updateOne
기본적으로 document를 찾을 때 query 형식은 findOne이나 find와 같다.
1
| { <field1>: { <operator1>: <value1> }, ... }
|
찾고자 하는 필드 속성에 operator와 값이 붙는 방식인데 해당 operator에 들어갈 수 있는 것들의 몇 가지 예시는 위의 read 관련 option과 같다.
1
2
3
4
5
| $or : n개 중 한 개라도 해당하면 반환
$and : n개 모두 다 해당해야 반환
$in : 해당 내용이 포함되어있으면 반환
$gte : 크거나 같으면 반환
$gle : 작거나 같으면 반환
|
이렇게 찾은 데이터를 바꾸는 게 필요한데 그 부분들에 대한 option도 여럿 지원한다. 그 option에 대한 내용은 아래와 같다.
1
2
3
4
| $set : 지정하는 속성으로 값을 바꾼다.
$unset : 해당 속성을 삭제한다.
$currentDate : 지정하는 속성의 값을 현재 시간으로 바꾼다.
$upsert : 해당하는 속성이 없으면 만들어서 넣는다.
|
updateOne이 조건에 맞는 document 한 개만 update 시키는 기능이다.
아래는 드라이버별 예시이다.
1
2
3
4
5
| // MongoDB Shell
// A 속성이 1인 도큐먼트 한 개의 B 속성값을 1로 만든다.
db.inventory.updateOne( { "A":1 },{"$set":{"B":1}} )
// A 속성이 0 이상인 도큐먼트 한 개의 B 속성을 1로 바꾸고, lastUpdated 속성을 현재 시간으로 지정한다.
db.inventory.updateOne({"A":{"$gte":0}},{"$set":{"B":1},"$currentDate": { "lastUpdated": true }})
|
1
2
3
4
5
| // Mongoose
// A 속성이 1인 도큐먼트 한 개의 B 속성값을 1로 만든다.
await inventoryCol.updateOne( { "A":1 },{"$set":{"B":1}} )
// A 속성이 0 이상인 도큐먼트 한 개의 B 속성을 1로 바꾸고, lastUpdated 속성을 현재 시간으로 지정한다.
await inventoryCol.updateOne( {"A":{"$gte":0}},{"$set":{"B":1},"$currentDate": { "lastUpdated": true }})
|
1
2
3
4
5
| # Pymongo
# A 속성이 1인 도큐먼트 한 개의 B 속성값을 1로 만든다.
data_inventory_col.update_one( { "A":1 },{"$set":{"B":1}} )
# A 속성이 0 이상인 도큐먼트 한 개의 B 속성을 1로 바꾸고, lastUpdated 속성을 현재 시간으로 지정한다.
data_inventory_col.update_one( {"A":{"$gte":0}},{"$set":{"B":1},"$currentDate": { "lastUpdated": true }} )
|
updateMany
기본적으로 document를 찾을 때 query 형식은 read query들과 updateOne과 같다.
1
| { <field1>: { <operator1>: <value1> }, ... }
|
찾고자 하는 필드 속성에 operator와 값이 붙는 방식인데 해당 operator에 들어갈 수 있는 것들의 몇 가지 예시는 위의 read 관련 option과 같다.
1
2
3
4
5
| $or : n개 중 한 개라도 해당하면 반환
$and : n개 모두 다 해당해야 반환
$in : 해당 내용이 포함되어있으면 반환
$gte : 크거나 같으면 반환
$gle : 작거나 같으면 반환
|
이렇게 찾은 데이터를 바꾸는 게 필요한데 그 부분들에 대한 option도 여럿 지원한다. 그 option에 대한 내용은 아래와 같다.
1
2
3
4
| $set : 지정하는 속성으로 값을 바꾼다.
$unset : 해당 속성을 삭제한다.
$currentDate : 지정하는 속성의 값을 현재 시간으로 바꾼다.
$upsert : 해당하는 속성이 없으면 만들어서 넣는다.
|
updateOne이 한 개만 변경하는 것이라면 updateMany는 조건에 맞는 다수 개의 document값을 update 시키는 기능이다.
아래는 드라이버별 예시이다.
1
2
3
4
5
| // MongoDB Shell
// A 속성이 1인 모든 도큐먼트의 B 속성값을 1로 만든다.
db.inventory.updateMany( { "A":1 },{"$set":{"B":1}} )
// A 속성이 0 이상인 모든 도큐먼트의 B 속성을 1로 바꾸고, lastUpdated 속성을 현재 시간으로 지정한다.
db.inventory.updateMany({"A":{"$gte":0}},{"$set":{"B":1},"$currentDate": { "lastUpdated": true }})
|
1
2
3
4
5
| // Mongoose
// A 속성이 1인 모든 도큐먼트의 B 속성값을 1로 만든다.
await inventoryCol.updateMany( { "A":1 },{"$set":{"B":1}} )
// A 속성이 0 이상인 모든 도큐먼트의 B 속성을 1로 바꾸고, lastUpdated 속성을 현재 시간으로 지정한다.
await inventoryCol.updateMany({"A":{"$gte":0}},{"$set":{"B":1},"$currentDate": { "lastUpdated": true }})
|
1
2
3
4
5
| # Pymongo
# A 속성이 1인 모든 도큐먼트의 B 속성값을 1로 만든다.
data_inventory_col.update_many( { "A":1 },{"$set":{"B":1}} )
# A 속성이 0 이상인 모든 도큐먼트의 B 속성을 1로 바꾸고, lastUpdated 속성을 현재 시간으로 지정한다.
data_inventory_col.update_many({"A":{"$gte":0}},{"$set":{"B":1},"$currentDate": { "lastUpdated": true }})
|
Delete
deleteOne
기본적으로 document를 찾을 때 query 형식은 read query들과 update query들과 같다.
1
| { <field1>: { <operator1>: <value1> }, ... }
|
찾고자 하는 필드 속성에 operator와 값이 붙는 방식인데 해당 operator에 들어갈 수 있는 것들의 몇 가지 예시는 위의 read 관련 option과 같다.
1
2
3
4
5
| $or : n개 중 한 개라도 해당하면 반환
$and : n개 모두 다 해당해야 반환
$in : 해당 내용이 포함되어있으면 반환
$gte : 크거나 같으면 반환
$gle : 작거나 같으면 반환
|
deleteOne은 조건에 맞는 document 한 개만 삭제하는 것이다.
아래는 드라이버별 예시이다.
1
2
3
4
5
| // MongoDB Shell
// A 속성이 1인 도큐먼트 한 개를 삭제한다.
db.inventory.deleteOne( { "A":1 } )
// A 속성이 0 이상인 도큐먼트 한 개를 삭제 한다.
db.inventory.deleteOne({"A":{"$gte":0}})
|
1
2
3
4
5
| // Mongoose
// A 속성이 1인 도큐먼트 한 개를 삭제한다.
await inventoryCol.deleteOne( { "A":1 } )
// A 속성이 0 이상인 도큐먼트 한 개를 삭제 한다.
await inventoryCol.deleteOne({"A":{"$gte":0}})
|
1
2
3
4
5
| # Pymongo
# A 속성이 1인 도큐먼트 한 개를 삭제한다.
data_inventory_col.delete_one({"A": 1})
# A 속성이 0 이상인 도큐먼트 한 개를 삭제 한다.
data_inventory_col.delete_one({"A":{"$gte":0}})
|
deleteMany
기본적으로 document를 찾을 때 query 형식은 read query들과 update query들과 같다.
1
| { <field1>: { <operator1>: <value1> }, ... }
|
찾고자 하는 필드 속성에 operator와 값이 붙는 방식인데 해당 operator에 들어갈 수 있는 것들의 몇 가지 예시는 위의 read 관련 option과 같다.
1
2
3
4
5
| $or : n개 중 한 개라도 해당하면 반환
$and : n개 모두 다 해당해야 반환
$in : 해당 내용이 포함되어있으면 반환
$gte : 크거나 같으면 반환
$gle : 작거나 같으면 반환
|
deleteMany는 조건에 맞는 document 여러개를 삭제하는 것이다.
아래는 드라이버별 예시이다.
1
2
3
4
5
| // MongoDB Shell
// A 속성이 1인 모든 도큐먼트를 삭제한다.
db.inventory.deleteMany( { "A":1 } )
// A 속성이 0 이상인 모든 도큐먼트를 삭제한다.
db.inventory.deleteMany({"A":{"$gte":0}})
|
1
2
3
4
5
| // Mongoose
// A 속성이 1인 모든 도큐먼트를 삭제한다.
await inventoryCol.deleteMany( { "A":1 } )
// A 속성이 0 이상인 모든 도큐먼트를 삭제한다.
await inventoryCol.deleteMany({"A":{"$gte":0}})
|
1
2
3
4
5
| # Pymongo
# A 속성이 1인 모든 도큐먼트를 삭제한다.
data_inventory_col.delete_many({"A": 1})
# A 속성이 0 이상인 모든 도큐먼트를 삭제한다.
data_inventory_col.delete_many({"A":{"$gte":0}})
|
참고자료