정승권 (Andrew Chung)
const BookSchema = new mongoose.Schema({
title: String,
author: String
});
BookSchema.index({ title: "text", author: "text" });
// 텍스트 인덱스를 사용해 검색하는 코드
Book.find({ $text: { $search: "안나 카레니나" } }, { score: { $meta: “textScore” } })
.then(results => console.log(results));인덱스 (Index) 란 ?
Book Index:
DB (Text) Index:
검색어: 안나 카레니나
"안나"
Token
"카레니나"
Matching document ids
[1, 3, 8]
[3]
MongoDB Full-Text Search (Whitespace Tokenizing)
ElasticSearch (Whitespace Tokenizing + Edge N-Grams Filter)
Author: 레프 톨스토이
Tokens: "레프", "톨스토이"
Author: 레프 톨스토이
Tokens: "레", "레프", "톨", "톨스", "톨스토", "톨스토이"
단어(토큰) 하나하나 당 여러개의 "n-gram"토큰을 생성
n-gram은 인덱스에서 여러개의 record/document로 매핑이 된다.
검색할 수 있는 키워드가 많아짐 → 부분 검색도 이제 가능
const settings = {
analysis: {
filter: {
autocomplete_filter: {
type: "edge_ngram",
min_gram: 1, // N-Gram 최소 길이
max_gram: 40 // N-Gram 최대 길이
}
},
analyzer: {
autocomplete: {
filter: ["lowercase", "autocomplete_filter"],
type: "custom",
tokenizer: "whitespace" // 토크나이징 방법
}
}
}
};
const booksBody = {
settings,
mappings: {
properties: {
authors: {
type: "text",
analyzer: "autocomplete" // edge_ngram 필터적용
},
title: {
type: "text",
analyzer: "autocomplete" // edge_ngram 필터적용
}
}
}
};// ElasticSearch Javascript API로 인덱스 만들기
client.indices.create({
index: "books",
body: booksBody
});const response = await client.search({
index: "books",
sort: "_score",
body: {
query: {
multi_match: {
query: "용기",
analyzer: "standard",
fields: ["authors", "title^2"]
}
}
}
});
// 결과를 콘솔로 찍기 (다음 슬라이드에 나옴)
console.log(response.body.hits)책 13885권이 되는 컬렉션에서 에서 "용기"를 찾아봤습니다.
const books = await Book.find({
$or: [
{ title: { $regex: new RegExp("용기", "i") } },
{ authors: { $regex: new RegExp("용기", "i") } }
]
});Regex Find:
ElasticSearch (Edge N-Grams)
const response = await client.search({
index: "books",
sort: "_score",
body: {
query: {
multi_match: {
query: "용기",
analyzer: "standard",
fields: ["authors", "title^2"]
}
}
}
});Avg: 199.286ms
Avg: 51.764ms