首頁  >  文章  >  後端開發  >  使用python和xapian建構高速檢索引擎

使用python和xapian建構高速檢索引擎

高洛峰
高洛峰原創
2016-10-18 10:03:171217瀏覽

首先弄清楚幾個概念:Documents 、terms and posting在資訊檢索(IR)中,我們企圖要取得的項稱之“document”,每一個document是被一個terms集合所描述的。 「document」和「term」這兩個詞彙是IR中的術語,它們是來自「圖書館管理學」的。通常一個document認為是一塊文本,(Usually a document is thought of as a piece of text, most likely in a machine readable form), 而一個term則是一個詞語或短語以用作描述document的,在document中大多數會存在多個term,例如某個document是跟_口腔_ _衛生_相關的,那麼可能會存在以下的terms:「tooth」、「teeth」、「toothbrush」、「decay」、「cavity 」、「plaque」或「diet」等等。

如果在一個IR系統中,存在一個名為D的document,此document被一個名為t的term所描述,那麼t被認為索引了D,可以用以下式子表 示:t->D。在實際應用的一個IR系統中通常是多個documents,如D1, D2, D3 …組成的集合,且有多個term,如t1, t2, t3 …組成的集合,從而有以下關係:ti -> Dj。

如果某個特定的term索引了某個特定的document,那麼稱之為posting,說白了posting就是帶position信息的term,在相關度檢索中可能有一定的用途的。

給定一個名為D的document,存在著一個terms列表索引著它,我們稱之為D的term list。

給定一個名為t的term,它索引著一個documents列表,這稱之為t的posting list(使用“Document list”可能會在叫法上更一致,但聽起來過於空泛)。

在一個存在於電腦的IR系統中,terms是儲存於索引檔案中的。 term可以用來作為有效地找出它的posting list,在posting list裡,每個document都帶有一個很短的標識符,就是document id。簡單來說,一個posting list可以被認為是一個由document ids組成的集合,而term list則是字串組成的集合。在某些IR系統的內部是使用數字來表示term的,因此在這些系統中,term list則是數字組成的集合,而Xapian則不是這樣,它使用原汁原味的term,而使用前綴來壓縮存儲空間。

Terms不一定是要是document中出現的詞語,通常它們會被轉換為小寫,而且往往它們被詞幹提取算法處理過,因此通過一個值為“connect” 的term可能會檢索出一系列的詞語,例「connect」、「connects」、「connection」或「connected」等,而一個詞語也可能產生多個的terms,例如你會將提取的詞乾和未提取的詞語都索引起來。當然,這可能只適用於英語、法語或拉丁語等歐美系列的語言,而中文的分詞則有很大的區別,總的來說,歐美語系的語言分詞與中文分詞有以下的區別:

l. 拿英文來說,通常英文的每一個字之間是用空格來隔開的,而中文則不然,甚至可以極端到整篇文章都不出現空格或標點符號。 2. 像上面提到的,「connect」、「connects」、「connection」或「connected」分別的意思「動詞性質的連結」、「動詞性質的第三人稱的連結」、「名稱性質的連結」或“連接的過去式”,但在中文裡,用“連接”就可以表示全部了,幾乎不需要詞幹提取。這意味著英文的各種詞性大部 分是有章可循的,而中文的詞性則是天馬行空的。 3. 第二點只是中文分詞非常困難的縮影,要完全正確地標識出某個句子的語意是很困難的,例如「中華人民共和國成立了」這個句子,可以分出「中華」、「華人」、「人民」、「共和國」、「成立」等詞語,不過其中「華人」跟這個句子其實關係不大。咋一眼看起來很簡單,但機器那有這麼容易懂這其中的奧妙呢?

Values

Values是附加在document上一種元數據,每一個document可以有多個values,這些values透過不同的數字來識別。 Values被設計成在匹配過程中快速地訪問,它們可以用作排序、排隊多餘重複的document和範圍檢索等用途。雖然values並沒有長度限制,但 最好讓它們盡可能短,如果你只是想儲存某個欄位以便作為結果顯示,那麼建議您最好將它們保存在document的data中。

Document data

每一個Document只有一個data,可以是任意類型格式的數據,當然在儲存的時候請先轉換為字串。這聽起來可能有點古怪,實情是這樣的:如果要儲存的資料是文字格式,則可以直接儲存;如果要儲存的資料是各種的對象,請先序列化成二進位串流再儲存,而在讀取的時候反序列化讀取。

posting

posting是帶position的term.

# -*- coding: gb18030 -*-
import xapian
testdatas = [u'abc test python1',u'abcd testing python2']
def buildtest():
    database = xapian.WritableDatabase('indexes/', xapian.DB_CREATE_OR_OPEN)
    stemmer = xapian.Stem("english")
    for data in testdatas:
        doc = xapian.Document()
        doc.set_data(data)
        for term in data.split():
            doc.add_term(term)
        database.add_document(doc)
if __name__ == '__main__':
    buildtest()

執行後,當前目錄下產生索引庫。

[sh]

[ec2-user@ip-10-167-6-221 indexes]$ ll

總用量 52

-rw-rw-r-- 1 ec2-user ec2-user    0  7月28 16:06 flintlock

-rw-rw-r-- 1 ec2-user ec2-user   28 170688 iam76

-rw-rw-r-- 1 ec2-user ec2-user   13  7月28 16:06 postlist.baseA

-rw-rw-r-- 1 ec2-user ec2-user   14 170 postlist.baseB

-rw-rw-r-- 1 ec2-user ec2-user 8192  7月28 16:06 postlist.DB

-rw-rw-r-- 1 ec2-user ec2-user

-rw-rw-r-- 1 ec2-user ec2-user   1313 28 16:06 record.baseA

-rw-rw-r-- 1 ec2-user ec2-user   14  7月28 16:06 record.baseB

-rw-rw-r-- 12-2-user ecec user 8192  7月28 16:06 record.DB

-rw-rw-r-- 1 ec2-user ec2-user   13  7月28 16:06 termlist.baseA

-w-w-1 -user ec2-user   14  7月28 16:06 termlist.baseB

-rw-rw-r-- 1 ec2-user ec2-user 8192  7月28 16:06 termlist.DB 如何介紹我們下篇

去查詢索引。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn