Setup Meilisearch with Node.js and MongoDB
Setup Meilisearch
docker run -d --name meilisearch -p 7700:7700 getmeili/meilisearch
Setup Node.js
npm install meilisearch
Example 1
Connect and setup
const { MeiliSearch } = require('meilisearch');
// Kết nối đến MeiliSearch
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700',
apiKey: 'API_KEY_CỦA_BẠN' // Nếu không có API Key, bạn có thể bỏ qua
});
// Tạo một chỉ mục mới (nếu chỉ mục chưa tồn tại)
const index = client.index('movies');
async function setupIndex() {
// Thêm một số dữ liệu vào chỉ mục
await index.addDocuments([
{ id: 1, title: 'The Shawshank Redemption', genre: 'Drama' },
{ id: 2, title: 'The Godfather', genre: 'Crime' },
{ id: 3, title: 'The Dark Knight', genre: 'Action' },
]);
console.log('Đã thêm dữ liệu vào chỉ mục');
}
async function searchMovies(query) {
const results = await index.search(query);
console.log('Kết quả tìm kiếm:', results.hits);
}
setupIndex().then(() => {
searchMovies('Godfather');
});
Setup searchable attributes and ranking
// Thiết lập các trường có thể tìm kiếm và xếp hạng
await index.updateSettings({
searchableAttributes: ['title', 'genre'],
rankingRules: ['words', 'typo', 'proximity', 'attribute', 'exactness'],
});
Example 2
Connect and setup
const { MeiliSearch } = require('meilisearch');
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700',
apiKey: 'YOUR_API_KEY', // Thay thế bằng API key nếu có
});
const productIndex = client.index('products');
async function addProducts() {
await productIndex.addDocuments([
{ id: 1, name: 'Laptop Acer', description: 'Laptop văn phòng', price: 15000000, category: 'electronics', tags: ['laptop', 'acer'] },
{ id: 2, name: 'Điện thoại Samsung', description: 'Điện thoại thông minh', price: 7000000, category: 'electronics', tags: ['phone', 'samsung'] },
// Các sản phẩm khác...
]);
}
addProducts();
Setup searchable, filterable, and sortable attributes
await productIndex.updateSettings({
searchableAttributes: ['name', 'description', 'category', 'tags'],
filterableAttributes: ['price', 'category'],
sortableAttributes: ['price'],
});
Query
async function searchProducts(query) {
const results = await productIndex.search(query, {
filter: 'category = "electronics" AND price >= 5000000', // Lọc theo danh mục và giá
sort: ['price:desc'], // Sắp xếp theo giá giảm dần
});
console.log(results.hits); // In kết quả tìm kiếm
}
searchProducts('laptop');
Filter and Paging
const results = await productIndex.search('phone', {
limit: 10, // Hiển thị 10 sản phẩm trên mỗi trang
offset: 0, // Trang đầu tiên
});
Sync data from database
With MongoDB
1. Background Job
const { MeiliSearch } = require('meilisearch');
const client = new MeiliSearch({ host: 'http://127.0.0.1:7700' });
// Hàm lấy dữ liệu từ cơ sở dữ liệu và đồng bộ vào MeiliSearch
async function syncDatabaseToMeiliSearch() {
const products = await getProductsFromDatabase(); // Hàm này trả về danh sách sản phẩm từ DB
const productIndex = client.index('products');
// Thêm hoặc cập nhật dữ liệu vào chỉ mục của MeiliSearch
await productIndex.addDocuments(products);
console.log('Đã đồng bộ dữ liệu với MeiliSearch');
}
// Thiết lập cron job chạy mỗi 5 phút
setInterval(syncDatabaseToMeiliSearch, 5 * 60 * 1000);
2. Listen database events
const { MongoClient } = require('mongodb');
const { MeiliSearch } = require('meilisearch');
const client = new MeiliSearch({ host: 'http://127.0.0.1:7700' });
const productIndex = client.index('products');
async function watchDatabaseChanges() {
const mongoClient = await MongoClient.connect('mongodb://localhost:27017');
const db = mongoClient.db('your_database');
const collection = db.collection('products');
const changeStream = collection.watch();
changeStream.on('change', async (change) => {
const { operationType, fullDocument } = change;
if (operationType === 'insert' || operationType === 'update') {
// Thêm hoặc cập nhật dữ liệu trong MeiliSearch
await productIndex.addDocuments([fullDocument]);
} else if (operationType === 'delete') {
// Xóa dữ liệu khỏi MeiliSearch
await productIndex.deleteDocument(change.documentKey._id);
}
console.log(`Đã đồng bộ thay đổi ${operationType} với MeiliSearch`);
});
}
watchDatabaseChanges();
3. Webhooks
async function addProductToDatabaseAndMeiliSearch(product) {
const newProduct = await addProductToDatabase(product);
await productIndex.addDocuments([newProduct]);
}
4. ETL
-
Airbyte
-
Apache NiFi
With PostgreSQL
1. LISTEN/NOTIFY and Trigger
CREATE FUNCTION notify_product_change() RETURNS TRIGGER AS $$
BEGIN
PERFORM pg_notify('product_changes', row_to_json(NEW)::text);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER product_change_trigger
AFTER INSERT OR UPDATE OR DELETE ON products
FOR EACH ROW EXECUTE FUNCTION notify_product_change();
const { Client } = require('pg');
const { MeiliSearch } = require('meilisearch');
const pgClient = new Client({
connectionString: 'postgresql://username:password@localhost:5432/mydatabase',
});
const meiliClient = new MeiliSearch({ host: 'http://127.0.0.1:7700' });
const productIndex = meiliClient.index('products');
async function startListening() {
await pgClient.connect();
await pgClient.query('LISTEN product_changes');
pgClient.on('notification', async (msg) => {
const productData = JSON.parse(msg.payload);
if (productData.id) {
// Đồng bộ dữ liệu với MeiliSearch
await productIndex.addDocuments([productData]);
console.log('Đã cập nhật dữ liệu sản phẩm trong MeiliSearch');
}
});
}
startListening();
2. Logical Replication
Logical replication in PostgreSQL allows you to track and retrieve data changes at the logical level, which can be used for real-time data synchronization. However, using this method requires more complex configuration and requires PostgreSQL version 10 or higher.
With MySQL
1. MySQL Binary Log (Binlog)
MySQL uses binlog to record any data changes, and you can use binlog to detect changes. There are libraries like mysql-binlog-streamer or tools like Debezium that can read binlog and detect changes in real time.
Using Debezium: This is an open source tool that acts as a CDC (Change Data Capture) system. Debezium can track changes in MySQL (or PostgreSQL) and pass them to Kafka or other systems that you can integrate with Node.js.
2. Trigger
Another solution is to use a trigger to log changes to an audit table and then set up a background job to read this table and sync with MeiliSearch.
Create trigger in MySQL
CREATE TRIGGER after_product_update
AFTER INSERT OR UPDATE OR DELETE ON products
FOR EACH ROW
BEGIN
INSERT INTO product_changes (operation, product_data) VALUES ('UPDATE', JSON_OBJECT('id', NEW.id, 'name', NEW.name, 'description', NEW.description));
END;
Sync data from product_changes table in Node.js
You can setup a cron job or background job in Node.js to read the product_changes table and sync with MeiliSearch.