만약 MySQL과 같은 SQL이었다면 검색을 위해 스핑크스나 엘라스틱서치를 사용하는 것이 필수였을 것입니다.
mongoDB도 마찬가지로 고급 검색 시스템을 적용하기 위해서는 검색엔진을 사용해야하는 것이 필수지만 간단한 기능을 구현하는 앱에서는 별다른 외부 서비스없이 text 인덱스만을 활용해서 검색 기능을 구현할 수 있습니다.
(오타 수정, 유의어 검색 등의 기술은 외부 서비스를 사용해야 합니다)
과거 인덱스를 다룬 포스트(https://darrengwon.tistory.com/671?category=870801)에서 text 인덱스를 살펴본 바가 있습니다.
text 인덱스
https://docs.mongodb.com/manual/core/index-text/
문자열 검색에 최적화된 인덱스입니다.
예를 들어 "해외 최신 영화"를 검색한다고 가정한다면, 유저는 "영화"라는 단어만 입력하지 문자열 전체를 '정확'하게 입력하는 경우는 별로 없습니다. 이러한 검색 기능을 도와주는 인덱스로 text 인덱스가 있습니다.
텍스트 인덱스는 하나의 컬렉션에 단 하나만 만들 수 있습니다.
text 인덱스의 독특한 점은, 검색 기능에 필요한 형태소 분석을 알아서 처리해준다는 것입니다. (검색 엔진에는 형태소 분석과 NLP가 동원됩니다. 검색 엔진만 따로 연구하기도 하니 상당히 어려운 분야임을 알 수 있습니다.)
일반적으로 검색 엔진은 다음과 같은 방식으로 작동한다고 합니다.
- 이용자가 넣은 키워드 혹은 문장을 읽어들인다.
- 문장이라면 키워드를 뽑아서 나눈다 (제일 가까운 병원 => '제일', '가까운', '병원')
- 데이터베이스에서 해당 키워드와 문장을 이용하여 검색을 돌린다.
- 해당 키워드 혹은 문장이 어디에 얼마나 포함되어 있는지에 따라 가중치를 적용하여 각 검색 결과에 점수를 메긴다.
- 점수에 따라 데이터를 정렬하여 결과 값을 이용자에게 보여준다.
여기에서 형태소 분석이 개입할 부분은 2번입니다. mongoDB의 경우 run을 검색하면 run 동사의 과거형 등 변형까지도 고려해 결과를 반환합니다. 아쉽게도 한국어는 이를 지원하지 않습니다. (어디서 듣기로는 유럽권 언어도 이를 지원한다고 하는데, 한국어도 지원이 되었으면 하는 바람입니다.)
섹션별로 찾은 후 contents를 검색하기 위해 다음과 같이 인덱스를 설정했습니다.
postSchema.index({ section: 1, contents: "text" });
shell에서 다음과 같이 인덱스를 찾아보니 등록이 되었군요
db.getCollection('posts').getIndexes()
// 인덱스 출력의 일부
"v" : 2,
"key" : {
"section" : 1,
"_fts" : "text",
"_ftsx" : 1
},
"name" : "section_1_contents_text",
"ns" : "KinoProject.posts",
"background" : true,
"weights" : {
"contents" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
이제 find 메서드로 해당하는 내용을 찾아내면 됩니다.
참고한 글)
'DB, ORM > 🍃mongoose, pymongo' 카테고리의 다른 글
mongoDB를 사용한 데이터의 Pagination 효율성 개선법 (3) | 2020.09.14 |
---|---|
mongoose populate를 통해 관계 Objectid를 통한 실제 객체를 추출하기 (0) | 2020.07.25 |
mongoose Schema option 이용하기 (0) | 2020.07.23 |
모델과의 관계 설정 (임베디드 방식/레퍼런스 방식) (0) | 2020.06.17 |
mongodb 기본 메서드 외 다른 살펴보기 (0) | 2020.06.10 |