Phần 4: ElasticSearch: Search in Depth
Bài đăng này đã không được cập nhật trong 7 năm
1. Finding Exact Values
Khi muốn tìm kiếm chính xác theo keywork thì bạn nên dùng các filter trong ES, và hãy dùng các filter nhiều nhất có thể bởi các filter sẽ không phải tính relevance
, tính score giữa input đầu vào và kết quả trả về
Các kết quả filter trả về được cache dễ dàng trên server do đó performance tìm kiếm sẽ tốt hơn nếu dùng full-text search.
- Term Filter: là filter được sử dụng thường xuyên, nó có khả năng xử lý
numbers
,Booleans
,dates
vàtext
.
Ví dụ: giả sử có một loạt các products
được index trong ES:
POST /my_store/products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3"}
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5"}
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }
- Tìm kiếm chính xác các
products
có giáprice = 20
sử dụng SQL:
SELECT document
FROM products
WHERE price = 20
- Dùng filter trong ES:
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"term" : {
"price" : 20
}
}
}
}
}
- Tìm kiếm sản phẩm có
productID = XHDK-A-1293-#fJ3
:
SELECT product
FROM products
WHERE productID = "XHDK-A-1293-#fJ3"
- Truy vấn dùng DSL:
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"term" : {
"productID" : "XHDK-A-1293-#fJ3"
}
}
}
}
}
Kết quả không như mong muốn vì productID
đã bị analyze bởi standard analyzer
, cần phải config không sử dụng analyzer cho field này
- Thay đổi mapping type cho
productID
để field này không được đánh index, sau đó bạn có thể dùng filter
DELETE /my_store
PUT /my_store
{
"mappings" : {
"products" : {
"properties" : {
"productID" : {
"type" : "string",
"index" : "not_analyzed"
}
}
}
}
}
- Combining Filters
Để tìm kiếm nhiều field trên một query, có thể kết hợp nhiều filter với nhau.
SELECT product FROM products
WHERE
(price = 20 OR productID = "XHDK-A-1293-#fJ3")
AND (price != 30)
Để viết câu query trên bằng DSL, cần dùng Boolean filter
- Bool Filter:
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}
- Nested Bool:
SQL query:
SELECT document
FROM products
WHERE productID= "KDKE-B-9947-#kL5"
OR (productID = "JODL-X-1937-#pV7" AND price = 30 )
Nested bool query:
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"productID" : "KDKE-B-9947-#kL5"}},
{ "bool" : {
"must" : [
{ "term" : {"productID" : "JODL-X-1937-#pV7"}},
{ "term" : {"price" : 30}}
]
}}
]
}
}
}
}
}
- Có rất nhiều các filter khác nhau giúp chúng ta có thể truy vấn các câu query như sử dụng SQL vây:
range
,exists
,missing
...
2. Full-Text Search
Match
Query: Là query để tìm kiếm full-text search. Trước tiên hãy đánh index cho một vài Document:
DELETE /my_index
PUT /my_index
{ "settings": { "number_of_shards": 1 }}
POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "title": "The quick brown fox" }
{ "index": { "_id": 2 }}
{ "title": "The quick brown fox jumps over the lazy dog" }
{ "index": { "_id": 3 }}
{ "title": "The quick brown fox jumps over the quick dog" }
{ "index": { "_id": 4 }}
{ "title": "Brown fox brown dog" }
- Tìm kiếm bởi một keyword:
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": "QUICK!"
}
}
}
Để thực thi câu query trên Elasticsearch sẽ làm những step sau:
-
Check the field type Check liệu xem field tìm kiếm có phải là field được config như một full-text ( analyzed ) string field hay không. Nếu có thì câu query cũng đường analyze
-
Analyze the query string
Query stringQUICK!
sẽ được xử lý bởi bộ standard analyzer. Vì câu này chỉ có một single term nên QUICK!
=> ``QUICK`
- Find matching docs
ES sẽ tìm trong inverted index xem có Document nào có chứa term QUICK
hay không. Trong trường hợp này sẽ là các documents 1, 2 và 3
- Score each doc
Tùy thuộc vào mức độ relevance
của keyword và kết quả match với document mà ES sẽ score cho mỗi kết quả trả về.
Score sẽ được đánh giả bởi thuật toán term frequency/inverse document frequency(TF/IDF) Thuật toán này sẽ đánh giá dựa vào một số yếu tố sau:
- Term frequency
Tần suất term xuất hiện trong field, term xuất hiện trong field càng nhiều thì điểm càng cao
- Inverse document frequency
Tần suất term xuất hiện trong mỗi document, term nào xuất hiện trong càng nhiều documents sẽ có điểm thấp hơn các term mà có trong chỉ vài Document
- Field-length norm
Term mà xuất hiện trong field ngắn hơn sẽ có điểm cao hơn là cũng term đó xuất hiện trong field có độ dài dài hơn
Trong full-text search vẫn còn rất nhiều topic cần tìm hiểu như:
- Improving precision
- Controlling precision
- Combining queries
- Controlling Analysis
Các bạn có thể tìm đọc cuốn Elasticsearch: The Definitive Guide
để tìm hiểu sâu hơn về các vấn đề này và về Elasticsearch nói chung
All rights reserved