app.get("/search", (req, res) => {
db.collection('post').find({todo: req.query.value}).toArray((err, result) => {
if(err) return console.log(err);
console.log(result);
res.render('search.ejs', {posts : result});
});
});
검색바 추가
<div class="container input-group mb-2">
<input class="form-control" id="search-input"/>
<button class="input-group-append btn btn-danger" id="search">검색</button>
</div>
<script>
$('#search').click(function() {
let inputValue = $('#search-input').val();
window.location.replace('/search?value=' + inputValue); // 현재 url 뒤에 붙여줄 것
})
</script>
<h1 class="ml-2 my-3 text-center">검색결과</h1>
<div class="container">
<ul class="list-group">
<% for (let i = 0; i < posts.length; i++) { %>
<li class="list-group-item">
<p>글번호 : <%= posts[i]._id %></p>
<a href="/detail/<%= posts[i]._id %>"><h4>할일 제목 : <%= posts[i].todo %></h4></a>
<p>날짜 : <%= posts[i].date %></p>
<button class="btn btn-danger delete" data-id="<%= posts[i]._id %>">삭제</button><p></p>
</li>
<% } %>
</ul>
</div>
<script>
$('.delete').click(function(e) {
var btnClick = $(this);
$.ajax({
method : 'DELETE',
url : '/delete',
data : {_id : e.target.dataset.id} // 삭제할 게시물 번호
}).done(function(result){
// 요청 성공 시 실행
console.log('삭제성공')
// 삭제 대상을 안보이게 처리하는 루틴
btnClick.parent('li').fadeOut();
}).fail(function(xhr, textStatus, errorThrown) {
// 요청 실패 시 실행
console.log('삭제실패')
})
})
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</body>
</html>
하지만 키워드를 모두 정확하게 입력하지 않으면 검색이 안됨
순차검색은 맨 처음부터 끝까지 순차적으로 찾아야하기 때문에 데이터가 많아질수록 효율이 떨어진다.
검색은 이분검색, 정렬은 버블정렬, 퀵정렬
mongoDB의 post 컬렉션에 Create Index.
type에 string이 아니라 text로 적어야한다. (문법임)
1로 적으면 숫자로 인식한다.
app.get("/search", (req, res) => {
// ────────────────── 일반적인 순차검색 ──────────────────
// db.collection('post').find({todo: req.query.value}).toArray((err, result) => {
// if(err) return console.log(err);
// console.log(result);
// res.render('search.ejs', {posts : result});
// });
// ────────────────── 바이너리 검색 ──────────────────
db.collection('post').find({$text : {$search : req.query.value}}).toArray((err, result) => {
if(err) return console.log(err);
console.log(result);
res.render('search.ejs', {posts : result});
});
});
키워드에 해당되는 것 모두 검색된다.
passportjs.org
글 작성 시 작성한 유저의 아이디를 불러온다.
passport를 통해 로그인 시 받아오는 user의 정보를 활용한다.
db.collection('post').insertOne({_id: totalCount + 1, writer : req.user._id , todo: req.body.title, date: req.body.date}, function(err, result) {
if(err) return console.log(err);
console.log('저장완료');
});
app.delete('/delete', function(req, res) {
console.log(req.body)
req.body._id = parseInt(req.body._id);
var deleteData = {_id : req.body._id , writer : req.user._id}
db.collection('post').deleteOne(deleteData, function(err) {
if(err) return console.log(err);
console.log('삭제완료');
res.status(200).send({message: '성공'})
})
})
<script>
$('.delete').click(function(e) {
var btnClick = $(this);
$.ajax({
method : 'DELETE',
url : '/delete',
data : {_id : e.target.dataset.id} // 삭제할 게시물 번호
}).done(function(result){
// 요청 성공 시 실행
console.log('삭제성공')
// 삭제 대상을 안보이게 처리하는 루틴
btnClick.parent('li').fadeOut();
location.reload();
}).fail(function(xhr, textStatus, errorThrown) {
// 요청 실패 시 실행
console.log('삭제실패')
})
})
</script>
삭제버튼을 클릭하면 데이터베이스에서 삭제가 되지 않아도 fadeOut 효과때문에 화면에서 사라지게 되므로 location.reload()
를 붙여서 새로고침을 시킨다.
그러면 사라지지 않은 데이터는 그대로 남아있게 된다.
코드를 작성하고 보니 server.js의 코드가 너무 길어졌다.
// 라우트 미들웨어 설정
app.use('/', require('./routes/webtoon.js'));
var router = require('express').Router();
router.get('/webtoon/drama', (req, res) => {
res.send('웹툰의 드라마입니다.');
})
router.get('/webtoon/action', (req, res) => {
res.send('웹툰의 액션입니다.');
})
module.exports = router;
app.use를 사용하면 전역 미들웨어가 된다.
부분 미들웨어는 아래 isLogin 같이 요청이 들어왔을때만 사용하는 미들웨어다.app.get('/mypage', isLogin, (req, res) => { res.render('mypage.ejs', {사용자 : req.user}); }); function isLogin(req, res, next) { if(req.user) { next(); // 다음으로 넘어감 } else { res.send('로그인 해주세요.'); } }
사용자가 / 루트로 요청을 했을때 하위 루트를 적용해달라는 의미이다.
/webtoon
으로 요청을 했다면
app.use('/webtoon', require('./routes/webtoon.js'));`
앞의 /webtoon
을 제외하면 된다.
router.get('/drama', (req, res) => {
res.send('웹툰의 드라마입니다.');
})
var router = require('express').Router();
var db;
const mongoClient = require('mongodb').MongoClient;
mongoClient.connect(
process.env.DB_URL,
function(err, client) {
if(err) return console.log(err);
db = client.db('TodoApp');
})
// list get 요청(페이지를 보여줘라)으로 접속하면
// 실제 DB에 저장된 데이터들로 예쁘게 꾸며진 HTML 보여주세요.
router.get('/list', function(req, res) {
// find()함수는 DB에서 모든 데이터를 가져와서 문자열로 변경
db.collection('post').find().toArray(function(err, result) {
// console.log(result);
res.render('list.ejs', {posts : result});
});
})
module.exports = router;
부분 미들웨어를 사용한다.
var router = require('express').Router();
router.get('/drama', isLogin, (req, res) => {
res.send('웹툰의 드라마입니다.');
})
router.get('/action', isLogin, (req, res) => {
res.send('웹툰의 액션입니다.');
})
function isLogin(req, res, next) {
if(req.user) {
next(); // 다음으로 넘어감
} else {
res.send('로그인 해주세요.');
}
}
module.exports = router;
로그인을 해야만 접근할 수 있는 페이지가 된다.
하지만 일일이 isLogin을 걸어주는 것이 번거로우므로 전역변수로 만들어준다.
router.use(isLogin)
var router = require('express').Router();
router.use(isLogin)
router.get('/drama', (req, res) => {
res.send('웹툰의 드라마입니다.');
})
router.get('/action', (req, res) => {
res.send('웹툰의 액션입니다.');
})
function isLogin(req, res, next) {
if(req.user) {
next(); // 다음으로 넘어감
} else {
res.send('로그인 해주세요.');
}
}
module.exports = router;
제한적인 페이지에 걸기
router.use('/drama', isLogin);
npm install multer
Multer는 파일 업로드를 위해 사용되는 multipart/form-data 를 다루기 위한 node.js 의 미들웨어.
multipart (multipart/form-data)가 아닌 폼에서는 동작하지 않는다.
// ────────────────── multer 설정 ──────────────────
let multer = require('multer');
let storage = multer.diskStorage({
destination : function(req, res, cb) {
cb(null, './public/image')
},
filename : function(req, file, cb) {
cb(null, file.originalname) // file.originalname : 파일 이름을 그대로 사용
}
});
let upload = multer({storage : storage});
app.get('/upload', function(req, res) {
res.render('upload.ejs');
})
app.post('/upload', upload.single('profile'), function(req, res) {
res.send('업로드 완료');
})
public/image 폴더에 업로드 된 이미지를 저장한다.
<h2 class="container mt-4"><strong>이미지 파일 업로드</strong></h2>
<div class="container mt-3">
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="profile" />
<button type="submit">전송</button>
</form>
</div>
app.get('/image/:imgname', function(req, res) {
res.sendFile(__dirname + '/public/image/' + req.params.imgname);
})
주소창에 경로를 입력하면 사진이 출력된다.