Manticore nhìn thì có vẻ dễ dùng nếu bạn có một nguồn dữ liệu thuần như mysql và cài đặt Manticore trực tiếp trên máy thay vì chạy Docker, nhưng đây là một công cụ nhiều tùy chọn và mình muốn dùng Docker để chạy, import nhiều nguồn dữ liệu khác như từ csv, json tới mysql, nên có rất nhiều vấn đề phức tạp xảy ra. Bài này ghi lại cách cài Manticore và chắc chắn là mình tự viết tay rồi, không có con AI nào cả :-)).
Lí do chọn đề tài. LOL. Đầu tiên, Melisearch viết bằng Rust và rất mới, chạy như điện, index nhanh, docker sạch sẽ, dễ xài, khổ nỗi chưa support tận răng cho tiếng Việt, khả năng customize chưa nhiều.
Ví dụ, nếu search “lủng củng” thì kết quả rất không ổn, vì “lưng cũng” hay “lưng cứng” cũng ra. Trong khi cài thử Elasticsearch thì nó ăn RAM kinh khủng (nghe nói có thể config được, nếu không nó ăn 50% RAM mặc định).
Đây là tấm ảnh về sự hơi củ chuối của Melisearch với tiếng Việt.
Đây là tốt hơn với Manticore, nhưng vẫn có sai số. Mình chỉ muốn tìm chính xác những văn bản chứa chính xác từ “lủng củng”. Mình test cùng một database.
Điều chỉnh truy vấn một chút thì kết quả sau cho thấy độ chính xác đúng như kì vọng với tiếng Việt. Khi chọn match_phrase thay vì match ban đầu theo thiết lập tùy chọn của Manticore, thì kết quả chỉ còn lại 20, đúng như kì vọng. Chú ý bạn có thể thử với sql, ở đây mình điều chỉnh trong Golang vì mình sẽ dùng HTTP để truy vấn thay vì SQL. Bạn có thể chọn 2 cách. Thậm chí dùng chính ngôn ngữ lập trình để kết nối thông qua SQL thay vì HTTP (RestAPI).
Ngoài Melisearch và Manticore thì còn Typesence đáng chú ý, hiện chưa thử. Elastic thì Java và có vẻ cần nhiều RAM khi test. Quyết định quay lại cái máng lợn Manticore (trước từng dùng Sphinx). Đây là report quá trình ấy.
Bình thường với kinh nghiệm chạy Melisearch thì mình chỉ mất khoảng dưới 1 tiếng để chuẩn bị dữ liệu và index. Thao tác với Melisearch cùng docker cơ bản là upload file dữ liệu json lên VPS và chạy tool index. Gắn code. Trước dùng PHP thì cũng import được từ chính PHP. Giờ có tool nên thôi. Và còn chuyển qua Golang nên chưa đụng client.
Ngoài ra, lần này sẽ dùng Manticore với Docker thay vì cài trực tiếp.
Cài Manticore với Docker
Do dùng Portainer nên cài Manticore rất đơn giản với 1 cái click chuột. Mình cần config để mount dữ liệu giữa container và host, mount config trên host và trong container, mount port.
Đây là hướng dẫn từ trang chủ, nếu bạn chạy lệnh docker trên máy thay vì dùng Portainer.
docker run -e EXTRA=1 --name manticore -v $(pwd)/data:/var/lib/manticore -p 127.0.0.1:9306:9306 -p 127.0.0.1:9308:9308 -d manticoresearch/manticore
Config trên host, upload data lên host, import (index) trong container
Manticore hỗ trợ các cách import dữ liệu như sau.
Tìm các container đang chạy:
sudo docker ps
Login vào bash của container:
docker exec -it dbcdc0e08227 bash //Thay dbcdc0e08227 bằng ID hoặc tên container của bạn. //Sau khi đăng nhập vào container, bạn gõ: indexer --help //Sẽ thấy một lô lốc các chỉ dẫn, lúc này, cần cấu hình (trên host và tư dộng mount vào container) để bắt đầu index.
Ảnh khi login vào container trong docker và chạy indexer
Log vào container và chạy searchd –help:
Cấu hình chỉ dẫn tiếng Việt
May có bài của thằng bạn già lngt để vọc, không lại mất công cả tuần (như nó, haha) để làm sao search ra tiếng Việt cho chuẩn.
Mout file config trên host (con VPS cài docker của mình) và container. Kết nối host và container, volume số 1 do container tự tạo, volume số 2 do mình đặt. Kết nối volumn giữa host và container.
Chuẩn bị file config trên host, mình sẽ lưu là là manticore.config và lưu vào /var/lib/docker/volumes/menticore_data/_data/manticore.conf trên VPS.
Vì mình đã map file config giữa host và container như sau:
/var/lib/docker/volumes/menticore_data/_data/manticore.conf|/etc/manticoresearch/manticore.conf
Chú ý về volume để lưu giữ liệu của Manticore khi bạn cài lại, nâng cấp, nếu không dữ liệu sẽ mất. Ngoài ra, mình sẽ thao tác chỉnh sửa file cấu hình trên host để hệ thống container tự động cập nhật, nhất là khi dùng nhiều hơn một file conf.
Đây là nội dung của file config, trước hết để test.
# Path to data directory for storing indexes data_dir = /var/lib/manticore # Source definition for data input source my_source { # Specify the type of source. Options: csvpipe, xmlpipe2, sql, etc. type = csvpipe # Command to load data from a CSV file csvpipe_command = cat /var/lib/manticore/data.csv # Define fields in the CSV and map them to Manticore fields csvpipe_field_string = title csvpipe_field_text = description csvpipe_field_uint = category_id csvpipe_attr_timestamp = created_at # Optional: a timestamp attribute } # Index definition to store the data from "my_source" index my_index { # Specify the data source to use for this index source = my_source # Path to where index files are stored path = /var/lib/manticore/my_index # Define additional options if needed (optional) min_word_len = 1 charset_type = utf-8 } # Real-time index for dynamic data updates index my_rt_index { type = rt # Real-time index type path = /var/lib/manticore/my_rt_index # Define real-time fields rt_field = title rt_field = description rt_attr_uint = category_id rt_attr_timestamp = created_at } # Searchd section for daemon settings searchd { # Port Manticore will listen on for queries listen = 9306:mysql41 # Log file paths query_log = /var/lib/manticore/query.log pid_file = /var/lib/manticore/searchd.pid # Networking settings listen = 9312:sphinx # Optional Sphinx protocol read_timeout = 5 client_timeout = 300 max_children = 30 }
Sử dụng manticore.conf trên host /var/lib/docker/volumes/menticore_data/_data/ (đã map vào column của container tại địa chỉ /var/lib/manticore/), thay vì dùng /etc/manticoresearch/manticore.conf mặc định trên container.
indexer –all -c /var/lib/manticore/manticore.conf
Đây là config để kết nối với mysql
# Define the data source source my_source { type = mysql #sql_host = localhost <== Sẽ không chạy vì manticore trên docker không kết nối với mysql trên host được. sql_host = 10.0.0.223 sql_user = english_dictionary sql_pass = abc12342141313 sql_db = english_dictionary sql_port = 3306 # The query used to fetch data from your source database sql_query = SELECT id, word, define FROM oxfordfixed_saoluu; #sql_attr_uint = id ==> handle automatically by Manticore } # Define the index that uses the source index my_index { source = my_source path = /var/lib/manticore/data/my_index } # Searchd configuration searchd { listen = 9306:mysql41 log = /var/lib/manticore/log/searchd.log query_log = /var/lib/manticore/log/query.log pid_file = /var/lib/manticore/log/searchd.pid } The Manticore configuration file you provided looks good for the most part. Here's a breakdown of the sections and some potential areas for improvement: 1. Data Source (source my_source) This section defines a data source named "my_source" which connects to a MySQL database. The connection details like sql_host, sql_user, sql_pass, and sql_db seem well-defined. Security Note: It's recommended to avoid storing the password directly in the configuration file. Consider using environment variables or a secure configuration management tool. 2. SQL Query (sql_query) The provided query seems to be fetching data from a table named oxfordfixed_saoluu with columns id, word, and define. This is likely appropriate for your use case. Make sure the table structure and columns match your expectations. 3. Index Definition (index my_index) This section defines an index named "my_index" that uses the data source "my_source". The path (/var/lib/manticore/data/my_index) seems reasonable for storing the index data. 4. Searchd Configuration (searchd) This section configures the search daemon (searchd). Listen Port: listen = 9306:mysql41 defines the port (9306) for MySQL connections and uses the "mysql41" protocol. This is appropriate for MySQL versions 4.1 and above. Logs: The configuration defines paths for various logs: log, query_log, and pid_file. Ensure these directories exist and have appropriate permissions. Potential Improvements: Character Encoding: Depending on your data and search needs, you might want to specify the character encoding for the data source and index (e.g., charset = utf8). Attribute Configuration: You've defined sql_attr_uint = id which likely indicates the primary key for the data. Consider adding more attributes based on your search needs (e.g., attr_string = word). Define attributes with appropriate data types (e.g., attr_string, attr_float, etc.) for efficient searching. Additional Resources: Manticore Search Manual: https://manual.manticoresearch.com/Server%20settings Manticore configuration file example: https://github.com/sphinx-doc/sphinx/blob/master/doc/conf.py Remember to restart Manticore after making any changes to the configuration file.
Lỗi khi kết nối với mysql (Trên host) và manticore (trên docker):
When using Docker with a bridge network, containers cannot directly access services running on the host machine by default. Here are a few ways to enable the Manticore container to connect to the MySQL instance on the host:
1. Use the Host IP Address
In many cases, using the host’s internal IP address in the local network (e.g., 192.168.x.x
) in the Manticore configuration should work. You can find the host IP address with:
ip addr show
Once you have the IP, use it in your Manticore configuration file to specify the MySQL connection, replacing localhost
with this IP.
Mình sửa host cho mysql trên file cấu hình manticore tại host: /var/lib/docker/volumes/menticore_data/_data
source my_source { type = mysql sql_host = 10.0.0.223 sql_user = english_dictionary sql_pass = your_mysql_password sql_db = english_dictionary sql_port = 3306
Một điều đáng chú ý là bạn phải mở cổng mysql trên host 3306 để manticore trong docker có thể truy xuất được.
Khi thử nghiệm, do cài lại Manticore trên VPS khác và vẫn dùng network tự tạo (mysql_phpmyadmin) trên docker nên mình vào portainer để thấy IP của network là 172.19.0.1. Mình sẽ khai báo:
sql_host = 172.19.0.1
# The query used to fetch data from your source database sql_query = SELECT id, word, define FROM oxfordfixed_saoluu; #sql_attr_uint = id ==> handle automatically by Manticore
Chạy docker để index:
sudo docker exec -it fb4fcd743b69 indexer my_index -c /var/lib/manticore/manticore.conf # bạn có thể thay ID của docker đang chạy manticore bằng tên cho dễ. sudo docker exec -it manticore indexer my_index -c /var/lib/manticore/manticore.conf
Với cách này thì mình đang dùng một file tùy chỉnh manticore.conf.
Thiết lập cho phép truy cập từ bên ngoài hay chỉ từ localhost
Manticore không support authentication kiểu API_KEY như trên Melisearch nên cần cấu hình port trên host hơi khác, gán 127.0.0.1:9306:9306 vào cổng của host. Nếu chỉ gán cổng cho Manticore 9036:9036 thì nó sẽ expose cổng 9036 ra ngoài (tất nhiên nếu bạn mở firewall với port kia trên VPS). Nếu gán 127.0.0.1:9306:9306 thì chắc chắn chỉ có localhost (của host hiện tại) truy cập được container kia dù bạn thiết lập mở cổng firewall hay không. Mình sẽ để mở cổng cho public khi test, import dữ liệu và khi xong sẽ thiết lập bảo vệ dữ liệu. Một điều đáng chú ý là khi khởi động lại docker thi phải chạy lại searchd nhằm khởi động lại. Nếu cài Manticore trực tiếp trên VPS thì có thể dùng systemd và chạy systemctl enable manticore để nó tự động khởi động. Do mình dùng Docker nên sẽ nói về việc làm sao khởi động lại searchd tự động ở phần sau.
Nếu chỉ cho phép truy cập trên localhost của máy chủ thì thiết lập cổng expose của máy chủ như sau. Đây cũng là hướng dẫn của Manticore. Như vậy, không cần phải có API_KEY như Melisearch, nhưng hạn chế là các ứng dụng phải cùng trên một máy. Muốn truy cập từ xa thì sẽ mở hoàn toàn.
Chỉ cho Docker expose dữ liệu trên host, thay vì public access như khi testing. Cách thực hiện: thay đổi thiết lập port khi khởi tạo Docker.
ports: - 127.0.0.1:9306:9306 - 127.0.0.1:9308:9308
Truy cập vào container và xem từng index một với 2 mysql server ở 2 cổng khác nhau (testrt có sẵn khi cài Manticore, nhưng do trùng cổng 9306 của mysql đang chạy trên host, nên phải đổi sang 9310).
Khắc phục lỗi searchd không chạy khi khởi động lại Docker
Khi khởi động lại Docker, mình nhận thấy searchd không chạy
Các tùy chọn trên file cấu hình
Một link rất quan trọng mà thiếu trên Docs. Đây là danh sách các setting của manticore từ searchd, indexer, source và common. 4 nội dung trên thường có trên file cấu hình của manticore dạng manticore.conf. Chú ý mình có thể dùng nhiều file cấu hình cho manticore và khi chạy indexer thì ghi thêm -c /path/cuztomized.conf để dùng cấu hình tùy chọn.
https://benwills.com/manticore-settings
Import dữ liệu từ file CSV thông qua indexer
Manticore requires the first column to represent the document id, which needs to be an unique integer number. If our CSV doesn’t have this, we can add it easy with an awk command:
https://play.manticoresearch.com/csv
- Cần thêm ID cho file CSV.
awk -v OFS=, ‘NR ==1 {print “ID”, $0; next} {print (NR-1), $0}’ nom_poetics.csv > poetics.csv
2) Gỡ header.
Manticore also requires to have no header in the CSV. In our sample CSV we have header, so we’re going to remove it:
3) Khai báo ĐẦY ĐỦ và đúng theo định dạng của file csv trong file manticore_news_data.conf (đây là file riêng dành cho loại tài liệu này muốn index). Tham khảo 2 link trên để match loại dữ liệu.
Nếu có 2 file config và dùng chung port cho mysql.
When using multiple Manticore configuration files, especially if they are listening on the same MySQL port, you can run into issues where only one of the configurations appears to work. Manticore only allows one instance of the searchd daemon to bind to a specific port (like 9310 for MySQL), and having multiple configuration files trying to bind to the same port can cause conflicts. Here are a few solutions and considerations:
Bước 1 index
indexer my_index –rotate -c /var/lib/manticore/manticore.conf
Bước 2 gọi để chạy
searchd -c /var/lib/manticore/manticore.conf
Mỗi lần khởi động lại docker, phải chạy lại
searchd -c /var/lib/manticore/manticore.conf
searchd -c /var/lib/manticore/manticore_poetic.conf
Check port đang sử dụng trong docker.
apt update
apt install -y net-tools
netstat -tuln
Vài notes:
1) Để chắc chắn là dữ liệu đã được index thì cần login vào mysql (của Manticore) để check. Xem ảnh sau sẽ thấy phải vào mysql trong container docker, dùng lệnh SHOW TABLES; rồi DESC poetic_nom; mới phát hiện ra nó chưa indexed. Đối chiếu với bảng my_index chạy trên một port khác thì đã index rồi. Nguyên nhân là khi import file csv, mình đã khai báo là attr_string thay vì field_string. Đối chiếu 2 kiểu khai báo đúng và sai của mình (thêm hậu tố _old và _update) để phân biệt).
Sau khi khai báo lại và chạy lại index. Kết quả đúng dữ liệu _old thì chưa có indexed còn _update ở dưới thì đã update đúng với mong muốn.
Thời gian index có thể lâu, tùy vào kích cỡ của tập tin. Chẳng hạn với 93GB, mình chờ 1-2 tiếng là xong. Khá nhanh.
2. Khai báo path trong index, không dùng data_dir. Tuy nhiên chú ý path phải có dạng folder/name, nếu không dữ liệu index được sẽ không được đưa vào folder.
Nếu path chỉ khai báo path = /var/lib/manticore/my_news thì my_news sẽ trở thành tiền tố của file sẽ được indexer extract ra, thay vì folder phụ.
3. Nếu dùng Docker thì phải chạy lại searchd mỗi khi container khởi động lại, tương tự như khi cài trên host.
4. Cuối cùng, quy trình tổng quan sử dụng Manticore có thể được hiểu như sau, trong đó với mỗi nguồn Import và Export đều có tập tin manticore_abc.conf riêng (hoặc gộp chung nếu muốn).
Bài này vẫn chưa đi chi tiết về việc chuyển dữ liệu qua lại giữa sql, csv, json và import vào hệ thống. Đáng chú ý: Tất cả các nội dung khai báo trong tập tin conf của Manticore phải thật chính xác, chẳng hạn khi import csv thì phải có UUID ở cột đầu tiên nhưng lại không có header của file, hay sự khác nhau giữa csvpipe_field_string (sẽ index) và csvpipe_attr_string (không index) khi import csv file.