Vì sao tìm kiếm tiếng Việt ở VCMS phải dùng cột sinh ra
Yêu cầu nghe đơn giản: gõ 'may giat' phải ra 'Máy giặt', và ngược lại. Postgres có `unaccent`, có `tsvector`, tưởng là xong trong một buổi chiều.
Chỗ nó gãy
ALTER TABLE posts ADD COLUMN search_tsv tsvector
GENERATED ALWAYS AS (to_tsvector('vietnamese', unaccent(title))) STORED;
-- ERROR: generation expression is not immutable`unaccent()` là VOLATILE, vì nó đọc một từ điển có thể đổi trong lúc chạy. Cột generated bắt buộc IMMUTABLE. Postgres không đoán, nó từ chối.
Cách đi vòng
CREATE OR REPLACE FUNCTION public.f_unaccent(text)
RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS $$
SELECT public.unaccent('public.unaccent', $1)
$$;Dạng hai tham số chỉ đích danh từ điển, nên kết quả không phụ thuộc `search_path` — đó là điều kiện để tuyên bố IMMUTABLE mà không nói dối. Cũng phải dùng `to_tsvector(regconfig, text)` hai tham số: dạng một tham số chỉ STABLE và cũng bị từ chối.
Thứ đáng nhớ
Khi Postgres nói 'not immutable', nó không bắt bẻ vặt. Nó đang nói: nếu cho phép, index sẽ trỏ vào dữ liệu không còn đúng nữa, và bạn sẽ mất hàng trong kết quả tìm kiếm mà không có lỗi nào báo.
Bình luận
Chưa có bình luận nào. Nếu bài này sai ở đâu, nói giúp.