1. Giới thiệu
Với đặc thù làm việc trong môi trường outsourcing Nhật nên các dự án không tránh khỏi việc sử dụng fullwidth, dự án của mình đang làm cũng vậy. Ồ thật ra trước khi bị QA bắt bug thì mình nghĩ chức năng tìm kiếm sử dụng Scout Elasticsearch Driver là khá uki rồi, vì nó hỗ trợ rất nhiều kiểu query từ search chính xác, search like,…. tuy nhiên dữ liệu dùng để tìm kiếm mới chỉ dừng lại ở text halfwidth. Để hiểu rõ hơn mình sẽ lấy một ví dụ nhé!
- Text có dạng fullwidth: アロハ, Aloha!
- Text có dạng halfwidth: アロハ, Aloha!
=> Khi bạn query “Aloha!” thì những records có text là” Aloha!” sẽ k được trả về.
Như vậy hiểu nôm na là fullwidth là những từ có độ rộng hơn halfwidth, muốn nhập được fullwidth ta phải cài đặt bộ gõ tiếng Nhật. Thông thường chúng ta sẽ sử dụng halfwidth nhiều hơn, nhưng trong một số trường hợp đặc biệt đôi khi khi làm việc với khách hàng Nhật chúng ta vẫn sử dụng fullwidth, thật may Elasticsearch hỗ trợ việc này. Vì vậy tiếp tục chuỗi series Elasticsearch hôm nay mình xin giới thiệu với các bạn một plugin giúp chúng ta tìm kiếm với fullwidth search.
2. Cách cài đặt
Để cài đặt plugin bạn run command sau:
sudo bin/elasticsearch-plugin install analysis-icu
Vậy là mình đã cài đặt xong plugin rồi, thật đơn giản đúng k ạ. Bạn có thể tìm hiểu kỹ hơn về ICU Analysis Plugin bạn có thể xem ở đây nhé!
3. Cách sử dụng
3.1 Tạo IndexConfigurator
php artisan make:index-configurator ElasticSearch/CategoryIndexConfigurator
Một file appElasticsearchCategoryIndexConfigurator.php sẽ được tạo ra, ở file này chúng ta setting đánh index cho đối tượng như sau:
<?php
namespace AppElasticSearch;
use ScoutElasticMigratable;
use ScoutElasticIndexConfigurator;
class CategoryIndexConfigurator extends IndexConfigurator
{
use Migratable;
/**
* @var array
*/
protected $settings = [
'analysis' => [
'normalizer' => [
'nfkc_cf_normalized' => [
'filter' => [
'lowercase',
'icu_normalizer',
],
],
],
],
];
}
Và để index hoạt động được bạn cần chạy lệnh sau:
php artisan elastic:create-index "AppElasticSearchCategoryIndexConfigurator"
3.2 Tạo Mapping Data
B1: Chúng ta tạo một Model Category có nội dung mapping như sau:
/**
* Mapping array
*
* @var array
*/
protected $mapping = [
'properties' => [
'id' => [
'type' => 'long',
],
'name' => [
'type' => 'keyword',
'normalizer' => 'nfkc_cf_normalized',
],
'description' => [
'type' => 'keyword',
'normalizer' => 'nfkc_cf_normalized',
],
],
];
B2: Tùy chỉnh data để đồng bộ hóa với từng chỉ mục tìm kiếm:
Sau khi tùy chỉnh mục tìm kiếm ( function toSearchableArray()) ta có được Category Model như sau
<?php
namespace AppModels;
use ScoutElasticSearchable;
use AppElasticSearchCategoryIndexConfigurator;
use IlluminateDatabaseEloquentModel;
class Category extends Model
{
use Searchable;
protected $indexConfigurator = AdminIndexConfigurator::class;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'description',
];
/**
* Mapping array
*
* @var array
*/
protected $mapping = [
'properties' => [
'id' => [
'type' => 'long',
],
'name' => [
'type' => 'keyword',
'normalizer' => 'nfkc_cf_normalized',
],
'description' => [
'type' => 'keyword',
'normalizer' => 'nfkc_cf_normalized',
],
],
];
/**
* Add field for search array
*
* @return array
*/
public function toSearchableArray()
{
$array = [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
];
return $array;
}
}
Bạn đừng quên đồng bộ hóa data bằng command nì nha:
php artisan elastic:update-mapping "AppModelsMyModel"
B3: Seed data mẫu
Ở đây mình sẽ seed 3 records có nội dung như sau:
$categories = [
[
'name' => 'Banh ngot',
'description' => 'Banh su kem, banh ga to',
],
[
'name' => 'Banh ngot',
'description' => 'Banh su kem, banh ga to',
],
[
'name' => 'banh ngot',
'description' => 'banh su kem, banh ga to',
],
];
B5: Import data
php artisan scout:import "AppModelsCategory"
Vậy là chúng ta đã cài đặt và cấu hình hoàn tất plugin analysis-icu rồi đó ạ ting ting ^^ . Cùng xem thành quả nhé
3.3 Search
Cả 3 ví dụ sau đây mình đều sử dụng
VD1: name = banh ngot (halfwidth)
VD2: name = Banh ngot (fullwidth)
VD3: name = Banh ngot (fullwidth + halfwidth)
Ở ba ví dụ trên cho dù bạn có sử dụng fullwidth hoặc halfwidth thì cũng đều ra cùng 1 kết quả.Thật tuyệt phải k ạ, vì plugin analysis-icu sẽ phân tích, chuẩn hóa cú pháp, hỗ trợ Unicode, chữ hoa, chữ thường cho câu lệnh query của chúng ta, không phân biệt fullwidth hay halfwidth.
4. Kết luận
Bài viết trên nhằm chia sẻ cho các bạn một plugin hữu ích, giúp chúng ta giải quyết được bài toán khi yêu cần search với fullwidth. Cảm ơn các bạn đã đọc bài viết của mình nhé
Tài liệu tham khảo: https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-icu.html#analysis-icu
Bài viết liên quan
[CSF-2] Một số thiết lập CSF, LFD
Hôm nay mình sẽ thực hiện một số thiết lập trên CSF Mở file config để sửa đổi một số tính năng dưới /etc/csf/csf.conf Nội dung chính1. Giới thiệu2. Cách cài đặt3. Cách sử dụng3.1...
[CSF-1] Tăng bảo mật Server với ConfigServer Firewall (CSF)
Nội dung chính1. Giới thiệu2. Cách cài đặt3. Cách sử dụng3.1 Tạo IndexConfigurator3.2 Tạo Mapping Data3.3 Search4. Kết luận1. Khái niệm CSF: CSF (ConfigServer & Firewall) là một bộ ứng dụng hoạt động trên Linux...
Sử dụng SSH Key với Gitlab và Github
Bài viết này mình sẽ hướng dẫn các bạn tạo ssh key cho Gitlab và Github SSH là gì? Secure Socket Shell là một giao thức mạng dùng để thiết lập kết nối mạng một...
Directory traversal vulnerabilities (phần 4)
Nội dung chính1. Giới thiệu2. Cách cài đặt3. Cách sử dụng3.1 Tạo IndexConfigurator3.2 Tạo Mapping Data3.3 Search4. Kết luậnV. Phân tích và khai thác các lỗ hổng Directory traversal (tiếp) 5. Bypass lỗ hổng khi...
Directory traversal vulnerabilities (phần 3)
Nội dung chính1. Giới thiệu2. Cách cài đặt3. Cách sử dụng3.1 Tạo IndexConfigurator3.2 Tạo Mapping Data3.3 Search4. Kết luậnV. Phân tích và khai thác các lỗ hổng Directory traversal 1. Lỗ hổng xảy ra khi...
Directory traversal vulnerabilities (phần 2)
Nội dung chính1. Giới thiệu2. Cách cài đặt3. Cách sử dụng3.1 Tạo IndexConfigurator3.2 Tạo Mapping Data3.3 Search4. Kết luậnIII. Vì sao lỗ hổng Directory traversal xuất hiện? Với mỗi ngôn ngữ lập trình khác nhau,...