검색 기능
일단 검색 창을 만들어주자.
list.ejs
이 검색창에서 키워드를 입력하고 검색을 누르면 새로운 페이지에서 검색결과를 보여주도록 구현해보자
1. 검색 버튼을 누르면 서버에 POST 요청을 해야한다
2. 서버는 DB에서 데이터를 꺼내줘야한다.
collection().findOne()
collection().find().toArray() 등을 활용하면 되겠다.
그런데 GET 요청으로도 서버로 데이터를 전달 가능하다.
GET 요청 시에 URL 뒤에 데이터를 심는 방법이다
URL query string
query string 작성법은 다음과 같다.
localhost:8080/list?데이터이름=데이터값
여러개를 입력한다면
데이터이름1=데이터값1&데이터이름2=데이터값2
이런 식이다.
이걸 query string 혹은 query parameter 라고 한다.
검색버튼에 id 를 search 로 설정하고
들어오는 input 값은 id를 search-input 으로 설정했다
만약 검색 버튼을 누르면 현재 URL의 주소를 /search?value=input 으로 바꾸도록 했다
여기서 input 은 위에 검색창에 입력했던 값이다.
검색버튼을 누르면 /search 로 GET 요청을 날리게 되고 value : (검색창에 입력한 값) 이라는 정보가 서버로 전달된다.
서버에서 query string 꺼내쓰기
req.query 를 출력해보면 value : (검색창에 입력한 값) 이 object 형식으로 들어있는 것을 확인할 수 있다.
post 라는 collection 에서
title 이 req.query.value 인 것을 찾아
콘솔에 출력하도록 했다.
제목이 333인 것을 검색해봤다
DB에서 title 이 333인 document 를 찾아준다.
근데 이런 식이면 title이 정확히 value 와 일치하는 것만 찾아준다.
검색 결과 페이지
위 내용을 바탕으로 검색 결과를 보여주는 result.ejs 페이지를 만들어봤다.
db에서 찾은 결과 데이터는 result에 들어있는데
이를 result_posts 라는 변수에 담아서 result.ejs 페이지로 전송했다
그리고 res.render() 를 써서 result.ejs 페이지를 화면에 보여주도록 했다(응답)
결과 페이지는 list.ejs 페이지와 화면상 동일하도록 했다.
대신에 보여주는 할일 리스트가 검색 결과 데이터로만 보여주도록했다.
아까 server.js 에서 result.ejs 로 보내준 result_posts 를 적절히 활용했다.
333 으로 검색했을 때에 해당하는 데이터만 화면에 결과로 출력되는 모습이다.
제대로 검색하기
지금은 정확히 데이터가 일치하는지만 확인해서 검색이 된다.(문제점)
해결하는 법은 정규식을 쓰는 방법이 있다.
/ / 안에 담아서 그 문자열이 포함되어있는지 확인하는 방법이다.
db.collection('post').find({제목 : /글쓰기/})
하지만 이렇게 하면 오래걸린다. (게시물이 1억개 있다면.....?)
find() 로 다 찾는 건 오래걸린다.
그래서 인덱싱을 해두면 게시물이 많아도 빨라진다.(binary seacrh 알고리즘 적용 가능하니까..)
Index 만들기
indexing 을 해두면 글자로 뭔가를 검색할 때에 매우 빠르게 찾을 수 있다.
몽고디비 아틀라스에 들어가보면 create index 버튼이 있다.
create index 를 눌러서
나는 title 기준으로 정렬을 해주려고 한다
만약 _id 같이 숫자라면 1이나 -1을 데이터타입으로 넣어줄 수 있다.
나는 title 이니 데이터 타입을 text 로 설정해준다.
Review 클릭.
참고 : Query string 쉽게 만들기(프론트엔드)
var 자료 = { 이름1 : '값1', 이름2 : '값2' }
$param(자료) //이름1=값1&이름2=값2 이거가 남음
이런식으로 쓰면 object 자료를 query string 으로 쉽게 변환 가능
$(폼태그를찾고).serialize()
위와 같이 serialize() 사용하면 폼태그안에 있는 모든 input 을 query string 으로 쉽게 변환해준다.
(이때 input 에는 name 속성이 있어야한다.)
네이버같은 검색기능 만들기
text index를 만들어두면 빠른 검색, OR 검색이 가능하다(둘중 하나만 써도 검색가능)
- 검색법과 " " 안에 넣어서 정확히 그 단어만 검색해주는 기능도 있다.
하지만 띄어쓰기 기준으로 단어를 저장해서 '안녕하세요' 라고 저장하면 '안녕'을 찾지못한다.
한글 친화적이지 못하다.
해결책
1. text index 를 쓰지말고 검색할 문서의 양을 제한한다.
맨 앞에 1000개에서만 찾아봐- 이런식이다.
2. text index 를 만들때 다르게 만들기.
띄어쓰기 단위로 indexing 하지 않도록 하고 다른 알고리즘을 쓰도록 세팅하는 방식이다.
3. search index 사용하기
몽고디비 아틀라스에서만 제공하는 기능이다.
search indexes 라는 탭으로 들어가보자
그러면 search index 를 생성할 수 있다.
이름은 titleSearch 라고 지어줬다
analyzer 설정을 lucene.korean 으로 바꿔준다.
한국어에 맞는 형태소분석기이다.
search index 이용해서 검색 요청하기
aggregate() 함수는 검색조건을 여러개 붙이고 싶을 때 유용한 함수이다.
이 함수안에 검색조건을 [ {검색조건1}, {검색조건2} ... ] 이런식으로 여러개 붙일 수 있다.
연산자 $search 를 쓰면 search index에서 검색이 된다.
그 밖에 여러 검색용 연산자가 있다
위 예시처럼 $sort, $limit, $project 등이다. (필요할 때 찾아서 쓰자)