Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- console.log
- MacOS
- node.js 연동
- mongodb
- Jupyter notebook
- nodejs mongodb
- Installation
- [Object]
- query
- python3
- node.js설치
- 맥에 파이썬 설치
- mongodb nodejs driver
- Windows10
- pip jupyter
- 파이썬3
- Projection
- util.inspect
- 맥
- mongo-native
- mongoDB [Object]
- homebrew
- collection.find
- Node.js
- MYSQL
Archives
- Today
- Total
Bon Voyage
'MongoDB in Action'으로 정리해보는 텍스트 검색 인덱스 본문
MongoDB in Actionhttps://book.naver.com/bookdb/book_detail.nhn?bid=6876243
9장 텍스트 검색 파트를 요약 정리했습니다.
개요
텍스트 검색 엔진 기능의 예시
- 대소문자 구분하지 않는 검색 Case-insensitive Search
- Java와 JavaScript를 구분한 검색 결과
정규 표현식으로 패턴 일치 검색을 해도 가능은 하지만, 인덱스 없이 대형 컬렉션에서 사용한다면 매우 느리다
개념 정리
1. 스테밍Stemming
- stem, root 단어, 단어의 원형과 변형들을 다 참고한다 (script → scripts, scripted, scripting)
2. 웹페이지 검색
- 페이지의 대형 네트워크를 검색하고, 페이지 간 관련도에 따라 결과의 순위를 정하는 검색방법
- 제품 데이터베이스 등 DB 데이터 검색 문제를 해결하기 위한 것은 아님
- 웹 페이지 네트워크 검색에 초점: DB에서 생성한 웹 페이지에 액세스하고, DB 자체에는 액세스 X
- 예를 들어 Java 책을 검색한다고 할 때, 책만 검색되지 않고 정오표 등 다른 검색결과 (noise)도 포함됨
3. Page Rank 검색 알고리즘
구글의 Larry Page가 개발한, 구글 검색 알고리즘 중 하나
- http://en.wikipedia.org/wiki/PageRank
- 하나의 페이지에 링크된 다른 페이지의 중요도를 토대로 해당 페이지의 중요도, 가중치를 평가한다
5. 전용 텍스트 검색 엔진
- 매우 큰 DB도 인덱싱 가능함
- 웹 검색 엔진에서 가능한 맞춤법 교정, 검색 제안, 관련성 측정 등의 기능을 지원함
- 추가 기능
— facets: 거의 모든 필드를 카테고리화, 범위 기반 그룹도 가능
— 사용자 정의 기능: 동의어 라이브러리, 형태소 분석(stemming) 알고리즘, 불용어 사전
MongoDB에서 가능한 텍스트 검색 기능 (지원되는 언어 기준, 한국어 불가)
- 형태소 분석 → 실시간 자동 인덱싱
- 필드에 가중치 선택적 지정
- 불용어 삭제
- 정확한 단어/구문 일치
- 특정 단어/구문 제외
→ 모든 기능은 인덱스 정의를 통해 사용 가능
→ 전체 DB를 검색용 엔진에 복사하지 않고도 적당히 단어 검색이 가능함
→ 전용 검색 엔진 관리 및 운영 비용을 피할 수 있음
HOW?
- 텍스트 검색에 필요한 인덱스를 정의한다
- 집계 프레임워크(aggregate), 기본 쿼리 등에서 텍스트 검색($text)을 사용한다
텍스트 검색 인덱스 정의
db.collection.createIndex(
{ field_name: 'text', //텍스트 인덱싱할 필드를 지정
...
//혹은 위를 생략하고 '$**'로 문자열을 포함하는 모든 인덱스를 선택할수도 있음
'$**': 'text'
},
{ weights: //필드의 가중치를 지정
{ field1_name: 10,
field2_name: 5,
... // 기본 가중치는 1, field1은 field2보다 2배 더 높은 가중치를 가지게 된다
}
},
[name: 'idx_name']
);
1. 정규 인덱스와의 차이점
- 인덱싱 필드에 대해 1, -1이 아니라 'text'를 넣는다
- 인덱싱되는 모든 필드 값 텍스트에서, 고유 단어들에 대해 인덱스 항목이 만들어진다
- 컬렉션당 하나의 텍스트 검색 인덱스를 가질 수 있다
(그러나 한 인덱스에 원하는 만큼 필드를 추가할 수 있다) - 필드 값 텍스트에서 불용어는 무시된다
2. 텍스트 인덱스 크기
- 텍스트 검색 인덱스는 컬렉션 자체보다 더 클 수 있다
- 불용어가 제거되더라도, 인덱스가 생성되는 대부분의 텍스트를 복제할 뿐 아니라
각 단어의 원본 도큐먼트에 대한 포인터를 추가해야 한다
- 불용어가 제거되더라도, 인덱스가 생성되는 대부분의 텍스트를 복제할 뿐 아니라
- 인덱스 이름의 길이가 너무 길 때:
- MongoDB에서 네임스페이스의 최대 길이는 120바이트 (V2.6~)
- 네임스페이스: db.collection.object의 이름
- name 속성으로 사용자 정의 이름을 주거나
- '$**'로 와일드카드 필드 이름을 지정한다
텍스트 검색 인덱스 사용 쿼리
1. 기본 검색
db.collection.find({$text: {$search: 'word_to_search'}}, {field_to_select: 1})
//word to search examples
'word'
' word '
'word1 or word2' //or는 제외되어 검색됨
'"exact word or phrases" or other_word' // "exact word~ "는 반드시 포함, 뒤는 or 매칭
'included or -"not included"' // -를 붙이면 제외하고 검색
$text
쿼리를 텍스트 검색으로 정의$search
검색에 사용할 문자열을 정의- 결과는 임의의 순서로 반환됨
- 자동으로 Stemming하여 어간으로 모든 도큐먼트를 찾기 위해 텍스트 검색 인덱스를 사용한다
- "" 쌍 따옴표를 붙이면 정확한 일치 조건, -를 붙이면 제외 조건
db.collection.find({$text: {$search: 'wordstofind'}, other_field: 'valuetofind'});
-
wordstofind를 포함하면서, other_field 필드에 valuetofind 값을 가지는 도큐먼트를 검색한다
텍스트 검색 기준 결합의 한계
- 다중 키 복합 인덱스, 지리공간 복합 키 인덱스는 허용X
- $text를 포함한 쿼리는 hint()를 사용할 수 없다
- 관련도에 따른 정렬 이외의 다른 정렬은 불가능함
2. 텍스트 검색 스코어 활용
textScore
→ 도큐먼트에 해당 단어가 표시된 횟수를 기반으로 도큐먼트간 관련성을 나타내는 숫자
1. 기본 find 쿼리
db.collection.find({$text: {$search: 'words to find'}},
{_id:0, field1: 1, score_val: {$meta: "textScore"}}).
limit(4);
// sort 가능함
db.collection.find({$text: {$search: 'words to find'}},
{_id:0, field1: 1, score_val: {$meta: "textScore"}}).
sort({score_val: {$meta: "textScore"}})
//find와 sort의 score_val은 동일하게 줘야 한다
- 결과에 텍스트 검색 스코어를 포함하여 검색
score_val
은 사용자 정의 항목- find쿼리에서는 find에서 준 score 이름을 sort에도 동일하게 줘야 한다
2. 집계 프레임워크 사용 (aggregate)
db.collection.aggregate(
[
{ $match: { $text: { $search: 'words to find' } } }, //검색
{ $sort: { $score_val: { $meta: 'textScore' } } }, //정렬
{ $project: { field1: 1, score_val: { $meta: 'textScore' } } } //추출
]
)
//sort, project 순서를 바꾸면 더 단순해진다
db.collection.aggregate(
[
{ $match: { $text: { $search: 'words to find' } } }, //검색
{ $project: { field1: 1, score_val: { $meta: 'textScore' } } } //추출
{ $sort: { $score_val: -1 }, //내림차순 정렬, $project의 score_name부분을 자동 참조함
]
)
aggregate의 텍스트 검색 시 제한 사항이 있다
- $text 사용할 때는 $match가 파이프라인의 첫 번째여야 하고,
$meta: 'textScore'가 등장하기 전에 와야 한다 - $text는 파이프라인에서 한 번만 사용 가능
- $text에서는 $or, $not을 사용할 수 없다
- ''가 or연산, ""가 정확한 일치(반드시 포함), -"" ( -'')는 not 연산이다
3. 텍스트 승수 multiplier
추가하기
비슷한 텍스트를 가지고 있는 도큐먼트라도, 포함된 field에 차이가 있는 경우 문서 간 관련도는 낮게 책정된다
→ 보정하고 싶다면, 텍스트 승수로 관련도 score 값을 보정할 수 있다
db.collection.aggregate(
[
{ $match: { $text: { $search: 'words to find' } } },
{ $project: { //1차 추출
field1_name: 1,
score_val: { $meta: 'textScore' },
multiplier: { $cond: [ '$field_to_adjust', 1.0, 3.0 ] } } },
// field_name, true, false
//이 필드가 있으면 multiplier의 값은 1.0, null이거나 없으면 3.0
{ $project: { //field 유무에 따른 문서간 관련도 점수 차이 보정
_id:0, field1_name:1, score_val:1,
adjScore: $multiply: ['$score_val', '$multiplier'] } },
{ $sort: { adjScore: -1 } } //조정된 점수를 기준으로 내림차순 정렬
]
)
텍스트 검색 언어 설정
언어별로 형태소 분석 내용이 달라진다, 하지만 불용어 사전은 사용자 정의 기능이 없다
하지만 '단순 언어 특수적 접미사 형태소 분석'을 사용할 뿐임: 더 많은 기능은 전용 텍스트 검색 엔진 사용하자
언어 설정 방법
-
인덱스 생성 시 지정
db.collection.createIndex( {'$**': 'text'}, {weights: {...}}, name: ..., default_language: 'language_to_set');
-
도큐먼트 삽입 시 지정
db.collection.insert({..., language: 'lang_to_set'});
-
텍스트 검색 시 지정
db.collection.find( {$text: {$search: 'words', $language: 'lang_to_find'}});
언어가 none
으로, 지정된 것이 없다면
- 오직 정확한 단어만이 형태소 분석 없이 인덱싱됨
- 불용어 제외되지 않음: 유사한 단어 검색 불가능
'개념 공부 > 데이터베이스' 카테고리의 다른 글
'MongoDB in Action'로 정리해보는 플러그형 스토리지 엔진 (0) | 2019.09.30 |
---|---|
'MongoDB in Action'으로 정리해보는 MongoDB의 인덱스 개념 (0) | 2019.09.29 |
'이것이 MySQL이다'로 정리해보는 인덱스 개념 (0) | 2019.09.28 |
Node.js MongoDB 드라이버 : collection.find() option 사용법 (0) | 2019.07.18 |
MongoDB Node.js 드라이버, 간단하게 시작해보기 (0) | 2019.07.17 |
Comments