Nhận một phần khớp từ cột TSVECTOR được lập chỉ mục GIN


13

Tôi muốn nhận kết quả bằng truy vấn này:

SELECT * FROM (
  SELECT id, subject
  FROM mailboxes
  WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;

Điều này hoạt động và trả về các hàng có tsvchứa Available. Nhưng nếu tôi sử dụng avai(bỏ lable) nó không thể tìm thấy bất cứ điều gì.

Có phải tất cả các truy vấn phải có trong từ điển? Chúng ta không thể truy vấn các chữ cái như vậy? Tôi có một cơ sở dữ liệu chứa nội dung e-mail (nội dung) và tôi muốn làm cho nó nhanh chóng khi nó tăng lên mỗi giây. Hiện tại tôi đang sử dụng

... WHERE content ~* 'letters`

Câu trả lời:


22

Có phải tất cả các truy vấn phải có trong từ điển?

Không. Bởi vì chỉ có từ gốc (theo cấu hình tìm kiếm văn bản đã sử dụng ) nằm trong chỉ mục để bắt đầu. Nhưng quan trọng hơn:

Không . Bởi vì, trên đầu trang Tìm kiếm toàn văn bản đó cũng có khả năng khớp tiền tố :

Điều này sẽ làm việc:

SELECT id, subject
FROM   mailboxes
WHERE  tsv @@ to_tsquery('simple', 'avail:*')
ORDER  BY id DESC;

Lưu ý 3 điều:

  1. Sử dụng to_tsquery(), không plainto_tsquery(), trong trường hợp này vì ( trích dẫn hướng dẫn ):

    ... plainto_tsquerysẽ không nhận ra tsquerytoán tử, nhãn trọng lượng hoặc nhãn khớp tiền tố trong đầu vào của nó

  2. Sử dụng 'simple'cấu hình tìm kiếm văn bản để tạo tsqueryvì bạn rõ ràng muốn sử dụng từ 'tận dụng' và không áp dụng từ gốc.

  3. Nối :*để làm cho nó trở thành một tìm kiếm tiền tố, tức là tìm tất cả các từ vựng bắt đầu bằng 'avail'.

Quan trọng: Đây là một tìm kiếm tiền tố trên các từ vựng (từ gốc) trong tài liệu. Kết hợp biểu thức chính quy không có ký tự đại diện ( content ~* 'avail') không hoàn toàn giống nhau! Cái sau không được neo trái (bắt đầu từ vựng) và cũng sẽ tìm thấy 'FOOavail', v.v.

Không rõ liệu bạn muốn hành vi được nêu trong truy vấn của bạn hoặc tương đương với biểu thức chính quy được thêm vào. Các chỉ mục trigram ( pg_trgm) như @Evan đã đề xuất là công cụ phù hợp cho việc đó. Có nhiều câu hỏi liên quan trên dba.SE, hãy thử tìm kiếm .

Tổng quat:

Bản giới thiệu

SELECT *
FROM (
   VALUES
     ('Zend has no framework')
   , ('Zend Framework')
   ) sub(t), to_tsvector(t) AS tsv
WHERE tsv @@ to_tsquery('zend <-> fram:*');
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1

Câu trả lời liên quan gần đây (chương Cách tiếp cận khác nhau để tối ưu hóa tìm kiếm ):

Email?

Vì bạn đã đề cập đến email, hãy lưu ý rằng trình phân tích tìm kiếm văn bản xác định email và không phân tách chúng thành các từ / từ vựng riêng biệt. Xem xét:

SELECT ts_debug('english', 'xangr@some.domain.com')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})

Tôi sẽ thay thế các dấu phân cách @.trong email của bạn bằng dấu cách ( ' ') để lập chỉ mục chứa các từ.

Ngoài ra, kể từ khi bạn đang đối phó với tên trong email, không phải với tiếng Anh (hoặc một số ngôn ngữ khác) từ , tôi sẽ sử dụng 'simple'cấu hình tìm kiếm văn bản để bắt nguồn vô hiệu hóa và các ngôn ngữ các tính năng:

Xây dựng ts_vectorcột với:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;

Tôi đang xóa câu trả lời của mình cho điều này bởi vì dù sao đi nữa vì tôi rõ ràng đã sai lần đầu tiên và tôi không muốn bị nhắc nhở về điều đó. Tôi có hai câu hỏi cho bạn 1) :*tài liệu được ghi ở đâu và 2) không nên đề cập đến việc xây dựng to_tsvector('simple'..)đi kèm với các hướng dẫn rằng việc truy vấn tsv đó trong tương lai sẽ yêu cầu cấu hình 'đơn giản' để phản đối? Tôi nghĩ bạn nên làm rõ sự phân nhánh của việc vô hiệu hóa bắt nguồn từ một tsvector / tsquery.
Evan Carroll

@EvanCarroll: Sử dụng cấu hình 'đơn giản' không cần thiết . Nó chỉ tránh được việc xuất phát (như 'chuột' thành 'chuột') có thể hoặc không thể mong muốn. Không mong muốn cho ví dụ đã cho. Hướng dẫn sử dụng: Tôi đã thêm các liên kết ở trên ...
Erwin Brandstetter

4
@EvanCarroll: Ngoài ra: Nghĩ rằng bạn đã sai lần đầu tiên , sẽ là lần thứ hai. Và điều đó sẽ sai, đệ quy. ;)
Erwin Brandstetter

2
@ErwinBrandstetter, Wow, cách của bạn chỉ cho tôi một tìm kiếm tốc độ đầy đủ. Trước khi bạn mất cách 0.380msđể có kết quả. Sau khi bạn mất cách 0.079 ms.
xangr

1
@xangr: Không, FTS chỉ cung cấp kết hợp tiền tố cho các từ vựng. Đối với bất cứ điều gì nhiều hơn, tìm đến pg_trgm. FTS nhanh hơn (với chỉ số nhỏ hơn). Bạn thậm chí có thể kết hợp cả hai chỉ mục ...
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.