日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

全文搜索(或者文本搜索)提供了確定滿足一個查詢的自然語言文檔的能力,并可以選擇將它們按照與查詢的相關度排序。最常用的搜索類型是找到所有包含給定查詢詞的文檔并按照它們與查詢的相似性順序返回它們。查詢相似性的概念非常靈活并且依賴于特定的應用。最簡單的搜索認為查詢是一組詞而相似性是查詢詞在文檔中的頻度。

文本搜索操作符已經在數據庫中存在很多年了。本數據庫中對文本數據類型提供了~~LIKEILIKE操作符,但是它們缺少現代信息系統所要求的很多基本屬性:

  • 即使對英語也缺乏語言的支持。正則表達式是不夠的,因為它們不能很容易地處理派生詞,例如satisfiessatisfy。你可能會錯過包含satisfies的文檔,盡管你可能想要在對于satisfy的搜索中找到它們。可以使用OR來搜索多個派生形式,但是這樣做太羅嗦也容易出錯(有些詞可能有數千種派生)。

  • 它們不提供對搜索結果的排序(排名),這使它們面對數以千計被找到的文檔時變得無效。

  • 它們很慢因為沒有索引支持,因此它們必須為每次搜索處理所有的文檔。

全文索引允許文檔被預處理并且保存一個索引用于以后快速的搜索。預處理包括:

  • 將文檔解析成記號*。標識出多種類型的記號是有所幫助的,例如數字、詞、復雜的詞、電子郵件地址,這樣它們可以被以不同的方式處理。原則上記號分類取決于相關的應用,但是對于大部分目的都可以使用一套預定義的分類。本數據庫中使用一個解析器*來執行這個步驟。其中提供了一個標準的解析器,并且為特定的需要也可以創建定制的解析器。

  • 將記號轉換成詞位*。和一個記號一樣,一個詞位是一個字符串,但是它已經被正規化,這樣同一個詞的不同形式被變成一樣。例如,正規化幾乎總是包括將大寫字母轉換成小寫形式,并且經常涉及移除后綴(例如英語中的ses)。這允許搜索找到同一個詞的變體形式,而不需要冗長地輸入所有可能的變體。此外,這個步驟通常會消除停用詞,它們是那些太普通的詞,它們對于搜索是無用的(簡而言之,記號是文檔文本的原始片段,而詞位是那些被認為對索引和搜索有用的詞)。本數據庫中使用詞典*來執行這個步驟。已經提供了多種標準詞典,并且為特定的需要也可以創建定制的詞典。

  • 為搜索優化存儲預處理好的文檔。例如,每一個文檔可以被表示為正規化的詞位的一個有序數組。與詞位一起,通常還想要存儲用于近似排名的位置信息,這樣一個包含查詢詞更“密集”區域的文檔要比那些包含分散的查詢詞的文檔有更高的排名。

詞典允許對記號如何被正規化進行細粒度的控制。使用合適的詞典,你可以:

  • 定義不應該被索引的停用詞。

  • 使用 Ispell 把同義詞映射到一個單一詞。

  • 使用一個分類詞典把短語映射到一個單一詞。

  • 使用一個 Ispell 詞典把一個詞的不同變體映射到一種規范的形式。

  • 使用 Snowball 詞干分析器規則將一個詞的不同變體映射到一種規范的形式。

我們提供了一種數據類型tsvector來存儲預處理后的文檔,還提供了一種類型tsquery來表示處理過的查詢。有很多函數和操作符可以用于這些數據類型,其中最重要的是匹配操作符@@。全文搜索可以使用索引來加速。

什么是一個文檔

一個document是在一個全文搜索系統中進行搜索的單元,例如,一篇雜志文章或電子郵件消息。文本搜索引擎必須能夠解析文檔并存儲詞位(關鍵詞)與它們的父文檔之間的關聯。隨后,這些關聯會被用來搜索包含查詢詞的文檔。

對于本數據庫中的搜索,一個文檔通常是一個數據庫表中一行內的一個文本形式的域,或者可能是這類域的一個組合(連接),這些域可能存儲在多個表或者是動態獲取。換句話說,一個文檔可能從用于索引的不同部分構建,并且它可能被作為一個整體存儲在某個地方。例如:

    SELECT title || ' ' ||  author || ' ' ||  abstract || ' ' || body AS document
    FROM messages
    WHERE mid = 12;

    SELECT m.title || ' ' || m.author || ' ' || m.abstract || ' ' || d.body AS document
    FROM messages m, docs d
    WHERE m.mid = d.did AND m.mid = 12;

注意

實際上在這些例子查詢中,coalesce應該被用來防止一個單一NULL屬性導致整個文檔的一個NULL結果。另一種存儲文檔的可能性是作為文件系統中的簡單文本文件。在這種情況下,數據庫可以被用來存儲全文索引并執行搜索,并且某些唯一標識符可以被用來從文件系統檢索文檔。但是,從數據庫的外面檢索文件要求超級用戶權限或者特殊函數支持,因此這種方法通常不如把所有數據放在本數據庫中內部方便。另外,把所有東西放在數據庫內部允許方便地訪問文檔元數據來協助索引和現實。對于文本搜索目的,每一個文檔必須被縮減成預處理后的tsvector格式。搜索和排名被整個在一個文檔的tsvector表示上執行 — 只有當文檔被選擇來顯示給用戶時才需要檢索原始文本。我們因此經常把tsvector說成是文檔,但是當然它只是完整文檔的一種緊湊表示。

基本文本匹配

本數據庫中的全文搜索基于匹配操作符@@,它在一個tsvector(文檔)匹配一個tsquery(查詢)時返回true。哪種數據類型寫在前面沒有影響:

    SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery;
     ?column?
    ----------
     t

    SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector;
     ?column?
    ----------
     f

正如以上例子所建議的,一個tsquery并不只是一個未經處理的文本,頂多一個tsvector是這樣。一個tsquery包含搜索術語,它們必須是已經正規化的詞位,并且可以使用 AND 、OR、NOT 以及 FOLLOWED BY 操作符結合多個術語。有幾個函數to_tsqueryplainto_tsquery以及phraseto_tsquery可用于將用戶書寫的文本轉換為正確的tsquery,它們會主要采用正則化出現在文本中的詞的方法。相似地,to_tsvector被用來解析和正規化一個文檔字符串。因此在實際上一個文本搜索匹配可能看起來更像:

    SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat');
     ?column?
    ----------
     t

注意如果這個匹配被寫成下面這樣它將不會成功:

    SELECT 'fat cats ate fat rats'::tsvector @@ to_tsquery('fat & rat');
     ?column?
    ----------
     f

因為這里不會發生詞rats的正規化。一個tsvector的元素是詞位,它被假定為已經正規化好,因此rats不匹配rat@@操作符也支持text輸出,它允許在簡單情況下跳過從文本字符串到tsvectortsquery的顯式轉換。可用的變體是:

    tsvector @@ tsquery
    tsquery  @@ tsvector
    text @@ tsquery
    text @@ text

前兩種我們已經見過。形式text @@ tsquery等價于to_tsvector(x) @@ y。形式text @@ text等價于to_tsvector(x) @@ plainto_tsquery(y)。在tsquery中,&(AND)操作符指定它的兩個參數都必須出現在文檔中才表示匹配。類似地,|(OR)操作符指定至少一個參數必須出現,而!(NOT)操作符指定它的參數出現才能匹配。例如,查詢fat & ! rat匹配包含fat但不包含rat的文檔。在<->(FOLLOWED BY) tsquery操作符的幫助下搜索可能的短語,只有該操作符的參數的匹配是相鄰的并且符合給定順序時,該操作符才算是匹配。例如:

    SELECT to_tsvector('fatal error') @@ to_tsquery('fatal <-> error');
     ?column?
    ----------
     t

    SELECT to_tsvector('error is not fatal') @@ to_tsquery('fatal <-> error');
     ?column?
    ----------
     f

FOLLOWED BY 操作符還有一種更一般的版本,形式是<``N``>,其中N是一個表示匹配詞位位置之間的差。<1><->相同,而<2>允許剛好一個其他詞位出現在匹配之間,以此類推。當有些詞是停用詞時,phraseto_tsquery函數利用這個操作符來構造一個能夠匹配多詞短語的tsquery。例如:

    SELECT phraseto_tsquery('cats ate rats');
           phraseto_tsquery
    -------------------------------
     'cat' <-> 'ate' <-> 'rat'

    SELECT phraseto_tsquery('the cats ate the rats');
           phraseto_tsquery
    -------------------------------
     'cat' <-> 'ate' <2> 'rat'

一種有時候有用的特殊情況是,<0>可以被用來要求兩個匹配同一個詞的模式。圓括號可以被用來控制tsquery操作符的嵌套。如果沒有圓括號,|的計算優先級最低,然后從低到高依次是&<->!。值得注意的是,當 AND/OR/NOT 操作符在一個 FOLLOWED BY 操作符的參數中時,它們表示與不在那些參數中時不同的含義,因為在 FOLLOWED BY 中匹配的準確位置是有意義的。例如,通常!x僅匹配在任何地方都不包含x的文檔。但如果y不是緊接在一個x后面,!x <-> y就會匹配那個y,在文檔中其他位置出現的x不會阻止匹配。另一個例子是,x & y通常僅要求xy均出現在文檔中的某處,但是(x & y) <-> z要求xy在緊挨著z之前的同一個位置匹配。因此這個查詢的行為會不同于x <-> z & y <-> z,它將匹配一個含有兩個單獨序列x z以及y z的文檔(這個特定的查詢一點用都沒有,因為xy不可能在同一個位置匹配,但是對于前綴匹配模式之類的更復雜的情況,這種形式的查詢就會有用武之地)。

配置

前述的都是簡單的文本搜索例子。正如前面所提到的,全文搜索功能包括做更多事情的能力:跳過索引特定詞(停用詞)、處理同義詞并使用更高級的解析,例如基于空白之外的解析。這個功能由文本搜索配置控制。本數據庫中有多種語言的預定義配置,并且你可以很容易地創建你自己的配置(psql 的\dF命令顯示所有可用的配置)。在安裝期間一個合適的配置將被選擇并且 default_text_search_config 也被相應地設置在postgresql.conf中。如果你正在對整個集簇使用相同的文本搜索配置,你可以使用在postgresql.conf中使用該值。要在集簇中使用不同的配置但是在任何一個數據庫內部使用同一種配置,使用ALTER DATABASE ... SET。否則,你可以在每個會話中設置default_text_search_config

依賴一個配置的每一個文本搜索函數都有一個可選的regconfig參數,因此要使用的配置可以被顯式指定。只有當這個參數被忽略時,default_text_search_config才被使用。為了讓建立自定義文本搜索配置更容易,一個配置可以從更簡單的數據庫對象來建立。本數據庫中的文本搜索功能提供了四類配置相關的數據庫對象:

  • 文本搜索解析器將文檔拆分成記號并分類每個記號(例如,作為詞或者數字)。

  • 文本搜索詞典將記號轉變成正規化的形式并拒絕停用詞。

  • 文本搜索模板提供位于詞典底層的函數(一個詞典簡單地指定一個模板和一組用于模板的參數)。

  • 文本搜索配置選擇一個解析器和一組用于將解析器產生的記號正規化的詞典。

文本搜索解析器和模板是從低層 C 函數構建而來,因此它要求 C 編程能力來開發新的解析器和模板,并且還需要超級用戶權限來把它們安裝到一個數據庫中(在本數據庫中發布的contrib/區域中有一些附加的解析器和模板的例子)。由于詞典和配置只是對底層解析器和模板的參數化和連接,不需要特殊的權限來創建一個新詞典或配置。創建定制詞典和配置的例子將在本章稍后的部分給出。