Thứ năm, 15/06/2017 | 00:00 GMT+7

Cách sử dụng tìm kiếm toàn văn bản trong PostgreSQL trên Ubuntu 16.04

Tìm kiếm toàn văn (FTS) là một kỹ thuật được các công cụ tìm kiếm sử dụng để tìm kết quả trong database . Nó được dùng để cung cấp các kết quả tìm kiếm trên các trang web như cửa hàng, công cụ tìm kiếm, báo chí, v.v.

Cụ thể hơn, FTS truy xuất các tài liệu , là các thực thể database có chứa dữ liệu dạng văn bản, không khớp hoàn toàn với các tiêu chí tìm kiếm. Điều này nghĩa là khi user tìm kiếm "mèo và chó", ví dụ: một ứng dụng do FTS hỗ trợ có thể trả về kết quả chứa các từ riêng biệt (chỉ "mèo" hoặc "chó"), chứa các từ theo thứ tự khác (“Chó và mèo”) hoặc chứa các biến thể của từ (“mèo” hoặc “chó”). Điều này mang lại lợi thế cho các ứng dụng trong việc đoán ý user và trả về các kết quả phù hợp hơn nhanh hơn.

Về mặt kỹ thuật, các hệ quản trị database (DBMS) như PostgreSQL thường cho phép tra cứu một phần văn bản bằng cách sử dụng mệnh đề LIKE. Tuy nhiên, các yêu cầu này có xu hướng hoạt động kém hơn trên các tập dữ liệu lớn. Chúng cũng bị giới hạn trong việc trùng với đầu vào chính xác của user , nghĩa là một truy vấn có thể không tạo ra kết quả, ngay cả khi có tài liệu với thông tin liên quan.

Sử dụng FTS, bạn có thể xây dựng một công cụ tìm kiếm văn bản mạnh mẽ hơn mà không cần đưa thêm phụ thuộc vào các công cụ nâng cao hơn. Trong hướng dẫn này, ta sẽ sử dụng PostgreSQL để lưu trữ dữ liệu có chứa các bài báo cho một trang web tin tức giả định, sau đó tìm hiểu cách truy vấn database bằng FTS và chỉ chọn các kết quả phù hợp nhất. Bước cuối cùng, ta sẽ triển khai một số cải tiến hiệu suất cho các truy vấn tìm kiếm toàn văn bản.

Yêu cầu

Trước khi bắt đầu hướng dẫn này, bạn cần các thành phần sau :

Nếu bạn cài đặt server PostgreSQL mà không làm theo hướng dẫn trên, hãy đảm bảo bạn có gói postgresql-contrib bằng sudo apt-get list postgresql-contrib .

Bước 1 - Tạo dữ liệu mẫu

Để bắt đầu, ta cần có một số dữ liệu để kiểm tra plugin tìm kiếm toàn văn bản, vì vậy hãy tạo một số dữ liệu mẫu. Nếu bạn đã có bảng của riêng mình với các giá trị văn bản, bạn có thể chuyển sang Bước 2 và thực hiện các thay thế thích hợp trong khi làm theo.

Nếu không, bước đầu tiên là kết nối với database PostgreSQL từ server của nó. Vì bạn đang kết nối từ cùng một server , theo mặc định, bạn sẽ không cần nhập password của bạn .

  • sudo -u postgres psql sammy

Điều này sẽ cài đặt một phiên PostgreSQL tương tác cho biết tên database bạn đang vận hành, trong trường hợp của ta là sammy . Bạn sẽ thấy một dấu nhắc lệnh database sammy=# .

Tiếp theo, tạo một bảng ví dụ trong database được gọi là news . Mỗi mục trong bảng này sẽ đại diện cho một tin bài với tiêu đề, một số nội dung và tên tác giả cùng với một số nhận dạng duy nhất.

  • CREATE TABLE news (
  • id SERIAL PRIMARY KEY,
  • title TEXT NOT NULL,
  • content TEXT NOT NULL,
  • author TEXT NOT NULL
  • );

id là index chính của bảng với loại đặc biệt SERIAL , tạo bộ đếm tăng tự động cho bảng. Đây là một mã định danh duy nhất sẽ tự động chuyển đến index database . Ta sẽ nói thêm về index này trong Bước 3 khi ta xem xét các cải tiến về hiệu suất.

Tiếp theo, thêm một số dữ liệu mẫu vào bảng bằng INSERT . Dữ liệu ví dụ này trong lệnh dưới đây đại diện cho một số bài báo mẫu.

  • INSERT INTO news (id, title, content, author) VALUES
  • (1, 'Pacific Northwest high-speed rail line', 'Currently there are only a few options for traveling the 140 miles between Seattle and Vancouver and none of them are ideal.', 'Greg'),
  • (2, 'Hitting the beach was voted the best part of life in the region', 'Exploring tracks and trails was second most popular, followed by visiting the shops and then checking out local parks.', 'Ethan'),
  • (3, 'Machine Learning from scratch', 'Bare bones implementations of some of the foundational models and algorithms.', 'Jo');

Bây giờ database có một số dữ liệu để tìm kiếm, ta có thể thử viết một số truy vấn.

Bước 2 - Chuẩn bị và Tìm kiếm Tài liệu

Bước đầu tiên ở đây là xây dựng một tài liệu với nhiều cột văn bản từ bảng database . Sau đó, ta có thể biến đổi chuỗi kết quả thành một vectơ từ, đó là những gì ta sẽ sử dụng trong các truy vấn.

Lưu ý: Trong hướng dẫn này, kết quả psql sử dụng định dạng expanded display thị từng cột từ kết quả trên một dòng mới, giúp dễ dàng điều chỉnh văn bản dài trên màn hình. Bạn có thể kích hoạt nó như thế này:

  • \x
Output
Expanded display is on.

Đầu tiên, ta cần đặt tất cả các cột lại với nhau bằng cách sử dụng hàm nối PostgreSQL || và biến đổi hàm to_tsvector() .

  • SELECT title || '. ' || content as document, to_tsvector(title || '. ' || content) as metadata FROM news WHERE id = 1;

Điều này trả về bản ghi đầu tiên dưới dạng toàn bộ tài liệu, cũng như version đã biến đổi của nó được sử dụng để tìm kiếm.

Output
-[ RECORD 1 ]----------------------------------------------------- document | Pacific Northwest high-speed rail line. Currently there are only a few options for traveling the 140 miles between Seattle and Vancouver and none of them are ideal. metadata | '140':18 'current':8 'high':4 'high-spe':3 'ideal':29 'line':7 'mile':19 'none':25 'northwest':2 'option':14 'pacif':1 'rail':6 'seattl':21 'speed':5 'travel':16 'vancouv':23

Bạn có thể nhận thấy rằng có ít từ hơn trong version đã chuyển đổi, metadata trong kết quả ở trên, so với trong document root . Một số từ khác nhau và mỗi từ đều có dấu chấm phẩy và một số được thêm vào. Điều này là do hàm to_tsvector() chuẩn hóa từng từ để cho phép ta tìm các dạng biến thể của cùng một từ, sau đó sắp xếp kết quả theo thứ tự bảng chữ cái. Số là vị trí của từ trong document . Có thể có thêm các vị trí được phân tách bằng dấu phẩy nếu từ chuẩn hóa xuất hiện nhiều lần.

Bây giờ ta có thể sử dụng tài liệu đã chuyển đổi này để tận dụng các khả năng của FTS bằng cách tìm kiếm thuật ngữ “Explorations”.

  • SELECT * FROM news WHERE to_tsvector(title || '. ' || content) @@ to_tsquery('Explorations');

Hãy xem xét các hàm và toán tử ta đã sử dụng ở đây.

Hàm to_tsquery() dịch tham số, có thể là tìm kiếm user trực tiếp hoặc được điều chỉnh một chút, thành tiêu chí tìm kiếm văn bản sẽ giảm đầu vào giống như cách mà to_tsvector() thực hiện. Ngoài ra, hàm cho phép bạn chỉ định ngôn ngữ sử dụng và liệu tất cả các từ phải có trong kết quả hay chỉ một trong số chúng.

Toán tử @@ xác định xem tsvector trùng với tsquery hoặc tsvector khác hay tsvector . Nó trả về true hoặc false , giúp bạn dễ dàng sử dụng như một phần của tiêu chí WHERE .

Output
-[ RECORD 1 ]----------------------------------------------------- id | 2 title | Hitting the beach was voted the best part of life in the region content | Exploring tracks and trails was second most popular, followed by visiting the shops and then checking out local parks. author | Ethan

Truy vấn trả về tài liệu có từ "Khám phá", mặc dù từ ta đang sử dụng để tìm kiếm là "Khám phá". Sử dụng toán tử LIKE thay vì FTS ở đây sẽ mang lại kết quả trống.

Bây giờ ta đã biết cách chuẩn bị tài liệu cho FTS và cách cấu trúc các truy vấn, hãy cùng xem các cách để cải thiện hiệu suất của FTS.

Bước 3 - Cải thiện hiệu suất FTS

Việc tạo tài liệu mỗi khi ta sử dụng truy vấn FTS có thể trở thành một vấn đề về hiệu suất khi sử dụng tập dữ liệu lớn hoặc server nhỏ hơn. Một giải pháp tốt cho điều này, mà ta sẽ thực hiện ở đây, là tạo tài liệu đã chuyển đổi khi chèn hàng và lưu trữ nó cùng với dữ liệu khác. Bằng cách này, ta có thể truy xuất nó bằng một truy vấn thay vì phải tạo nó mỗi lần.

Đầu tiên, tạo một cột bổ sung được gọi là document vào bảng news hiện có.

  • ALTER TABLE news ADD "document" tsvector;

Bây giờ ta cần sử dụng một truy vấn khác để chèn dữ liệu vào bảng. Không giống như Bước 2, ở đây ta cũng cần chuẩn bị tài liệu đã chuyển đổi và thêm nó vào cột document mới, như sau:

  • INSERT INTO news (id, title, content, author, document)
  • VALUES (4, 'Sleep deprivation curing depression', 'Clinicians have long known that there is a strong link between sleep, sunlight and mood.', 'Patel', to_tsvector('Sleep deprivation curing depression' || '. ' || 'Clinicians have long known that there is a strong link between sleep, sunlight and mood.'));

Việc thêm một cột mới vào bảng hiện có yêu cầu ta phải thêm các giá trị trống cho cột document lúc đầu. Bây giờ ta cần cập nhật nó với các giá trị đã tạo.

Sử dụng lệnh UPDATE để thêm dữ liệu bị thiếu.

  • UPDATE news SET document = to_tsvector(title || '. ' || content) WHERE document IS NULL;

Việc thêm các hàng này vào bảng của ta là một cải thiện hiệu suất tốt, nhưng trong tập dữ liệu lớn, ta có thể vẫn gặp sự cố vì database vẫn sẽ phải quét toàn bộ bảng để tìm các hàng phù hợp với tiêu chí tìm kiếm. Một giải pháp dễ dàng cho việc này là sử dụng các index .

Chỉ mục database là một cấu trúc dữ liệu lưu trữ dữ liệu tách biệt với dữ liệu chính giúp nâng cao hiệu suất của các hoạt động truy xuất dữ liệu. Nó cập nhật sau bất kỳ thay đổi nào trong nội dung bảng với chi phí ghi bổ sung và không gian lưu trữ tương đối ít. Kích thước nhỏ và cấu trúc dữ liệu được điều chỉnh cho phép các index hoạt động hiệu quả hơn nhiều so với việc sử dụng không gian bảng chính để chọn các truy vấn.

Cuối cùng, các index giúp database tìm thấy các hàng nhanh hơn bằng cách sử dụng các cấu trúc dữ liệu và thuật toán đặc biệt. PostgreSQL có một số loại index phù hợp với các loại truy vấn cụ thể. Những cái phù hợp nhất cho trường hợp sử dụng này là index GiST và index GIN. Sự khác biệt chính giữa chúng là tốc độ chúng có thể lấy tài liệu từ bảng. GIN xây dựng chậm hơn khi thêm dữ liệu mới, nhưng nhanh hơn khi truy vấn; GIST xây dựng nhanh hơn, nhưng yêu cầu đọc dữ liệu bổ sung.

Vì GiST truy xuất dữ liệu chậm hơn khoảng 3 lần so với GIN, ta sẽ tạo index GIN ở đây.

  • CREATE INDEX idx_fts_search ON news USING gin(document);

Sử dụng cột document được lập index , truy vấn SELECT của ta cũng trở nên đơn giản hơn một chút.

  • SELECT title, content FROM news WHERE document @@ to_tsquery('Travel | Cure');

Đầu ra sẽ như thế này:

Output
-[ RECORD 1 ]----------------------------------------------------- title | Sleep deprivation curing depression content | Clinicians have long known that there is a strong link between sleep, sunlight and mood. -[ RECORD 2 ]----------------------------------------------------- title | Pacific Northwest high-speed rail line content | Currently there are only a few options for traveling the 140 miles between Seattle and Vancouver and none of them are ideal.

Khi hoàn tất, bạn có thể thoát khỏi console database bằng \q .

Kết luận

Hướng dẫn này đề cập đến cách sử dụng tìm kiếm toàn văn trong PostgreSQL, bao gồm cả việc chuẩn bị và lưu trữ tài liệu metadata và sử dụng index để cải thiện hiệu suất. Nếu bạn muốn tìm hiểu thêm về FTS trong PostgreSQL, hãy xem tài liệu PostgreSQL chính thức về tìm kiếm toàn văn .


Tags:

Các tin liên quan

Cách bảo mật PostgreSQL chống lại các cuộc tấn công tự động
2017-01-24
Cách sử dụng Postgresql với Ứng dụng Django của bạn trên Debian 8
2016-12-22
Cách di chuyển thư mục dữ liệu PostgreSQL đến vị trí mới trên Ubuntu 16.04
2016-07-27
Cách sử dụng PostgreSQL với Ứng dụng Django của bạn trên Ubuntu 16.04
2016-05-18
Cách cài đặt và sử dụng PostgreSQL trên Ubuntu 16.04
2016-05-04
Cách backup, khôi phục và di chuyển database PostgreSQL với Barman trên CentOS 7
2016-01-20
Cài đặt postgresql 9.4 trên Debian 8
2015-06-11
Cách sử dụng PostgreSQL với Ứng dụng Django của bạn trên Ubuntu 14.04
2015-03-25
Cách sử dụng PostgreSQL với Ứng dụng Django của bạn trên CentOS 7
2015-03-25
Cách sử dụng PostgreSQL với ứng dụng Ruby on Rails của bạn trên Ubuntu 14.04
2015-03-18