목차
- Waht is MongoDB?
- NoSQL을 대표하는 데이터베이스
- JSON 형태로 데이터를 저장한다.
- mongodb cluster 가입하기
https://cloud.mongodb.com/ : 클라우드 데이터 베이스를 생성하기 mongodb+srv://kooks7:<password>@cluster0-s8bpd.gcp.mongodb.net/test?retryWrites=true&w=majority
-
$ npm i --save mongodb -
app.js 에 기존에 있던 'sequealize' 코드 지우기
const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); const errorController = require('./controllers/error'); const app = express(); app.set('view engine', 'ejs'); app.set('views', 'views'); const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); app.use(bodyParser.urlencoded({ extended: false })); app.use(express.static(path.join(__dirname, 'public'))); // 이 함수는 즉시 실행되는 것이 아니라 요청이 들어오면 실행됨으로 서버 실행 후 실행된다. // req.user라는 객체를 생성한다. app.use((req, res, next) => { // User.findByPk(1) // .then(user => { // req.user = user; // next(); // }) // .catch(err => console.log(err)); }); app.use('/admin', adminRoutes); app.use(shopRoutes); app.use(errorController.get404); app.listen(4000);
-
util/database.js 에서 mongodb 연결하고 app.js 에 가져오기
-
uilt/database.js
const mongodb = require('mongodb'); const MongoClient = mongodb.MongoClient; const mongoConnect = callback => { MongoClient.connect( 'mongodb+srv://kooks7:123123a@cluster0-s8bpd.gcp.mongodb.net/test?retryWrites=true&w=majority' ) .then(client => { console.log('connected!!'); callback(client); }) .catch(err => { console.log(err); }); }; module.exports = mongoConnect;
-
app.js
const mongoConnect = require('./util/database'); mongoConnect(client => { console.log(client); app.listen(4000); });
-
models에서 mongoDB에 계속 연결을 하기 위해 uilt/database.js 수정
const mongodb = require('mongodb'); const MongoClient = mongodb.MongoClient; let _db; const mongoConnect = callback => { MongoClient.connect('mongodb://localhost:27017/test') .then(client => { console.log('connected!!'); _db = client.db(); callback(client); }) .catch(err => { console.log(err); throw err; }); }; const getDb = () => { if (_db) { return _db; } throw 'No database found!'; }; exports.mongoConnect = mongoConnect; exports.getDb = getDb;
-
app.js 수정
const mongoConnect = require('./util/database').mongoConnect; mongoConnect(() => { app.listen(4000); });
-
models.product.js 수정
const getDb = require('../util/database').getDb; class Product { constructor(title, price, description, imageUrl) { this.title = title; this.price = price; this.description = description; this.imageUrl = imageUrl; } save() { const db = getDb(); return db.collection('products') .insertOne(this) .then(result => { console.log(result); }) .catch(err => { console.log(err); }); } } module.exports = Product;
-
-
controllers/admin.js 에
postAddProduct수정하기exports.postAddProduct = (req, res, next) => { const title = req.body.title; const imageUrl = req.body.imageUrl; const price = req.body.price; const description = req.body.description; const product = new Product(title, price, description, imageUrl); product .save() .then(result => { console.log('Created Product'); res.redirect('/'); }) .catch(err => { console.log(err); }); };
-
우리 홈페이지에서 새로운 product를 입럭하면 Compass에서 볼 수 있다.
-
models/product.js 에서 데이터베이스에 있는 모든 데이터 가져오는
fetchAll메서드 만들기class Product { constructor(title, price, description, imageUrl) { this.title = title; this.price = price; this.description = description; this.imageUrl = imageUrl; } save() { const db = getDb(); return db .collection('products') .insertOne(this) .then(result => { console.log(result); }) .catch(err => { console.log(err); }); } static fetchAll() { const db = getDb(); // promise를 반환하지 않고 cursor를 반환한다. cursor는 일종의 object이다. return db .collection('products') .find() .toArray() .then(products => { console.log(products); return products; }) .catch(err => { console.log(err); }); } }
-
controllers/shop.js 에
getProducts함수 수정exports.getProducts = (req, res, next) => { Product.fetchAll() .then(products => { res.render('shop/product-list', { prods: products, pageTitle: 'All Products', path: '/products' }); }) .catch(err => { console.log(err); }); };
-
models/product.js 수정하기
static findById(prodId) { const db = getDb(); return db .collection('products') // mongoDB는 Id 값을 특별한 object로 비교하기 때문에 이렇게 해줘야 한다. .find({ _id: new mongodb.ObjectID(prodId) }) .next() .then(product => { console.log(product); return product; }) .catch(err => { console.log(err); }); } }
이렇게 수정하는게 더 나아보인다.
static findById(prodId) { const db = getDb(); return db .collection('products') .findOne({ _id: new mongodb.ObjectId(prodId) }) .then(product => { // console.log(product); return product; }) .catch(err => { console.log(err); }); } }
-
controllers/admin.js 에 있는
getEditProduct함수 수정하기exports.getEditProduct = (req, res, next) => { const editMode = req.query.edit; if (!editMode) { return res.redirect('/'); } const prodId = req.params.productId; Product.findById(prodId) .then(product => { if (!product) { return res.redirect('/'); } res.render('admin/edit-product', { pageTitle: 'Edit Product', path: '/admin/edit-product', editing: editMode, product: product }); }) .catch(err => { console.log(err); }); };
-
models/product.js 수정하기
// constructor에 id 추가하기 constructor(title, price, description, imageUrl, id) { this.title = title; this.price = price; this.description = description; this.imageUrl = imageUrl; this._id = id ? new mongodb.ObjectId(id) : null; // 여기서 mongodb object로 바꿔주기 } // 기존에 존재하면 업데이터 하고 없으면 생성 save() { const db = getDb(); let dbOp; if (this._id) { // update the product dbOp = db .collection('products') .updateOne({ _id: new mongodb.ObjectId(this._id) }, { $set: this }); } else { dbOp = db.collection('products').insertOne(this); } return dbOp .then(result => { console.log(result); }) .catch(err => { console.log(err); }); }
-
controllers/admin.js 수정
// 함수 exports.postEditProduct = (req, res, next) => { const prodId = req.body.productId; const updatedTitle = req.body.title; const updatedPrice = req.body.price; const updatedImageUrl = req.body.imageUrl; const updatedDesc = req.body.description; exports.postEditProduct = (req, res, next) => { const prodId = req.body.productId; const updatedTitle = req.body.title; const updatedPrice = req.body.price; const updatedDesc = req.body.description; const updatedImageUrl = req.body.imageUrl; console.log(prodId); const product = new Product( updatedTitle, updatedPrice, updatedDesc, updatedImageUrl, prodId ); product .save() .then(result => { console.log('Updated'); res.redirect('/admin/products'); }) .catch(err => { console.log(err); }); };
-
models/product.js 에
deleteById메서드 추가static deleteById(prodId) { const db = getDb(); return db .collection('products') .deleteOne({ _id: new mongodb.ObjectId(prodId) }) .then(result => { console.log('Delete!'); }) .catch(err => { console.log(err); }); } }
-
controllers/admin.js 수정
exports.postDeleteProduct = (req, res, next) => { const prodId = req.body.productId; Product.deleteById(prodId) .then(() => { res.redirect('/admin/products'); }) .catch(err => console.log(err)); };
-
models/user.js 생성하기
const mongodb = require('mongodb'); const getDb = require('../util/database').getDb; class User { constructor(username, email) { this.name = username; this.eamil = email; } save() { const db = getDb(); return db.collection('users').insertOne(this); } static findById(userId) { const db = getDb(); return db .collection('users') .findOne({ _id: new mongodb.ObjectId(userId) }); } } module.exports = User;
-
comapss에 수동으로 users 컬렉션 생성해주고 app.js에 하드코딩으로 유저 넣기
app.use((req, res, next) => { User.findByPk('5e4bab8f7f305654f0adac0f') .then(user => { req.user = user; next(); }) .catch(err => console.log(err)); next(); });
-
제품 생성할 때 생성한 User 정보 넣기 위해 models/product 수정
constructor(title, price, description, imageUrl, id, userId) { this._id = id ? new mongodb.ObjectId(id) : null; this.title = title; this.price = price; this.description = description; this.imageUrl = imageUrl; this.userId = userId; }
-
controllers/admin.js 수정
exports.postAddProduct = (req, res, next) => { const title = req.body.title; const imageUrl = req.body.imageUrl; const price = req.body.price; const description = req.body.description; const product = new Product( title, price, description, imageUrl, null, req.user._id ); product .save() .then(result => { console.log('Created Product'); res.redirect('/'); }) .catch(err => { console.log(err); }); };
-
각각의 유저는 각자의 카트를 가지므로 model/user.js 클래스에 카트 담는 메서드 넣기
addToCart(product) { // const cartProduct = this.cart.items.findIndex(cp => { // return cp._id === product._id; // }); // Cart에 아무것도 담겨 있지 않을 때 const updatedCart = { items: [{ productId: new mongodb.ObjectId(product._id), quantity: 1 }] }; const db = getDb(); return db .collection('users') .updateOne( { _id: new mongodb.ObjectId(this._id) }, { $set: { cart: updatedCart } } ); }
-
app.js 데이터베이스에서 가져온 user 정보로 새 User 인스턴스 만들기
app.use((req, res, next) => { User.findById('5e4bab8f7f305654f0adac0f') .then(user => { req.user = new User(user.name, user.email, user.cart, user._id); next(); }) .catch(err => console.log(err)); });
-
controllers/shop.js 에 postCart 함수 재 작성
exports.postCart = (req, res, next) => { const prodId = req.body.productId; Product.findById(prodId) .then(product => { return req.user.addToCart(product); }) .then(result => { console.log(result); }); };
-
modles/user.js 에 addToCart 함수 수정 ( 카트에 제품 추가하는 기능)
addToCart(product) { // cart에 제품 있는지 조회 ? 양수 : -1 const cartProductIndex = this.cart.items.findIndex(cp => { return cp.productId == product._id; }); let newQuantity = 1; const updatedCartItems = [...this.cart.itmes]; // cart에 제품 있으면 if (cartProduct >= 0) { newQuantity = this.cart.items[cartProductIndex].quantity + 1; updatedCartItems[cartProductIndex].quantity = newQuantity; // cart에 제품 없으면 } else { updatedCartItems.push({ productId: new mongodb.ObjectId(product._id), quantity: newQuantity }); } const updatedCart = { items: updatedCartItems }; const db = getDb(); return db .collection('users') .updateOne( { _id: new mongodb.ObjectId(this._id) }, { $set: { cart: updatedCart } } ); }
-
models/user.js 카트 보여주는 기능 추가
getCart() { const db = getDb(); const productsIds = this.cart.items.map(i => { return i.productId; }); return db .collection('products') .find({ _id: { $in: productsIds } }) .toArray() .then(products => { return products.map(p => { return { ...p, quantity: this.cart.items.find(i => { return i.productId.toString() === p._id.toString(); }).quantity }; }); }); }
-
controllers/shop.js 수정
exports.postCart = (req, res, next) => { const prodId = req.body.productId; Product.findById(prodId) .then(product => { return req.user.addToCart(product); }) .then(result => { console.log(result); }); };
-
models/user.js delete 함수 추가
deleteItemFromCart(productId) { const updatedCartItems = this.cart.items.filter(item => { return item.productId.toString() !== productId.toString(); }); const db = getDb(); return db .collection('users') .updateOne( { _id: new mongodb.ObjectId(this._id) }, { $set: { cart: { items: updatedCartItems } } } ); }
-
controllers/shop.js 수정
exports.postCartDeleteProduct = (req, res, next) => { const prodId = req.body.productId; req.user .deleteItemFromCart(prodId) .then(result => { res.redirect('/cart'); }) .cathc(err => { console.log(err); }); };
-
models/user.js 에 addOrder() 추가
addOrder() { const db = getDb(); return this.getCart() .then(products => { const order = { items: products, user: { _id: new mongodb.ObjectId(this._id), name: this.name } }; return db.collection('orders').insertOne(order); }) .then(result => { this.cart = { items: [] }; return db .collection('users') .updateOne( { _id: new mongodb.ObjectId(this._id) }, { $set: { cart: { items: [] } } } ); }); }
-
controllers/shop.js 에 postOrder 수정
exports.postOrder = (req, res, next) => { let fetchedCart; req.user .addOrder() .then(result => { res.redirect('/orders'); }) .catch(err => { console.log(err); }); };
-
models/user.js getOrder 함수 수정
getOrders() { const db = getDb(); return db .collection('orders') .find({ 'user._id': new mongodb.ObjectId(this._id) }) //''를 이용해 중첩된 데이터를 찾음 .toArray(); }
-
controllers/shop.js 수정
exports.getOrders = (req, res, next) => { req.user .getOrders() .then(orders => { res.render('shop/orders', { path: '/orders', pageTitle: 'your Orders', orders: orders }); }) .catch(err => console.log(err)); };