[Whoosh 搜索引擎之 四 ] 模式設(shè)計

模式設(shè)計

關(guān)于模式和字段

模式指定索引中文檔的字段。

每個文檔可以有多個字段,比如標題、內(nèi)容、url、日期等。

一些字段可以被索引,一些字段可以與文檔一起存儲,以便字段值在搜索結(jié)果中可用。一些字段將被索引和存儲。

模式是文檔中所有可能字段的集合。每個單獨的文檔可能只使用模式中可用字段的一個子集。

例如,用于索引電子郵件的簡單模式可能包含 from_addrto_addr、subject、bodyattachments 等字段 ,其中 attachments 字段列出了電子郵件附件的名稱。對于沒有附件的電子郵件,您可以省略附件字段。

內(nèi)置字段類型

Whoosh 提供了一些有用的預(yù)定義字段類型:

whoosh.fields.TEXT
這種類型用于正文。它索引(并可選地存儲)文本并存儲術(shù)語位置以允許短語搜索。

TEXT 字段默認使用 StandardAnalyzer 分析器。要指定不同的分析器,請在構(gòu)造函數(shù)中使用 analyzer 參數(shù),例如 TEXT(analyzer=analysis.StemmingAnalyzer()). 請參閱 關(guān)于分析器。

默認情況下,TEXT 字段存儲每個索引術(shù)語的位置信息,以允許您搜索短語。如果您不需要能夠在文本字段中搜索短語,您可以關(guān)閉存儲術(shù)語位置以節(jié)省空間。使用 TEXT(phrase=False)。

默認情況下,TEXT 不存儲字段。通常您不想將正文存儲在搜索索引中。通常您可以根據(jù)搜索結(jié)果閱讀或鏈接到索引文檔本身,因此您不需要將它們的文本存儲在搜索索引中。但是,在某些情況下它可能很有用(請參閱 如何創(chuàng)建突出顯示的搜索結(jié)果摘錄)。使用 TEXT(stored=True) 指定將文本存儲在索引中。

whoosh.fields.KEYWORD
此字段類型專為以空格或逗號分隔的關(guān)鍵字而設(shè)計。這種類型是索引和可搜索的(并且可以選擇存儲)。為了節(jié)省空間,它不支持短語搜索。

要將字段的值存儲在索引中,請在構(gòu)造函數(shù)中使用 stored=True 。要在索引關(guān)鍵字之前自動將關(guān)鍵字小寫,請使用 lowercase=True.

默認情況下,關(guān)鍵字以空格分隔。要改為用逗號分隔關(guān)鍵字(以允許關(guān)鍵字包含空格),請使用 commas=True.

如果您的用戶需要使用 KEYWORD 字段進行搜索,請使用 scorable=True.

whoosh.fields.ID
字段 ID 類型只是將字段的整個值作為一個單元進行索引(并可選地存儲)也就是說,它不會將其分解為單獨的術(shù)語。這種類型的字段不存儲頻率信息,因此它非常緊湊,但對于評分不是很有用。

ID 用于 URL 或路徑(文檔的 URL 或文件路徑)、日期、類別等字段,這些字段的值必須作為一個整體來處理,并且每個文檔只能有一個值使用此類型。

默認情況下,ID 字段不存儲。使用 ID(stored=True) 指定字段的值應(yīng)與文檔一起存儲以用于搜索結(jié)果。例如,您可能希望存儲 URL 字段的值,以便您可以在搜索結(jié)果中提供指向原始內(nèi)容的鏈接。

whoosh.fields.STORED
該字段與文檔一起存儲,但未編入索引且不可搜索。這對于您希望在搜索結(jié)果中向用戶顯示但不需要能夠搜索到的文檔信息很有用。

whoosh.fields.NUMERIC
該字段以緊湊、可排序的格式存儲整數(shù)、長整數(shù)或浮點數(shù)。

whoosh.fields.DATETIME
該字段以緊湊、可排序的格式存儲日期時間對象。

whoosh.fields.BOOLEAN
這個簡單的字段索引布爾值并允許用戶搜索 yes, no, true, false, 1, 0,tf。

whoosh.fields.NGRAM
待定。

專家用戶可以創(chuàng)建自己的字段類型。

創(chuàng)建模式

創(chuàng)建一個模式:

from whoosh.fields import Schema, TEXT, KEYWORD, ID, STORED
from whoosh.analysis import StemmingAnalyzer

schema = Schema(from_addr=ID(stored=True),
                to_addr=ID(stored=True),
                subject=TEXT(stored=True),
                body=TEXT(analyzer=StemmingAnalyzer()),
                tags=KEYWORD)

如果您不需要為預(yù)定義字段構(gòu)造函數(shù)指定任何參數(shù),則可以省略括號(例如,使用 fieldname=TEXT 替代 fieldname=TEXT())。Whoosh 將為您實例化該類。

或者,您可以使用 SchemaClass 基類以聲明方式創(chuàng)建模式:

from whoosh.fields import SchemaClass, TEXT, KEYWORD, ID, STORED

class MySchema(SchemaClass):
    path = ID(stored=True)
    title = TEXT(stored=True)
    content = TEXT
    tags = KEYWORD

您可以將聲明類傳遞給實例 create_in()create_index() 代替 Schema 實例。

索引后修改架構(gòu)

創(chuàng)建索引后,您可以使用 add_field()remove_field() 方法向模式添加或刪除字段。這些方法在 Writer 對象上:

writer = ix.writer()
writer.add_field("fieldname", fields.TEXT(stored=True))
writer.remove_field("content")
writer.commit()

(如果您要修改模式并使用同一編寫器添加文檔,則必須在添加任何文檔之前調(diào)用 add_field()remove_field

為了方便起見,這些方法也在 Index 對象上,但是當您在 Index 上調(diào)用它們時 ,Index 對象只是創(chuàng)建編寫器,在其上調(diào)用相應(yīng)的方法,然后提交,因此如果您想要添加或刪除多個字段,自己創(chuàng)建編寫器效率更高:

ix.add_field("fieldname", fields.KEYWORD)

filedb 后端,刪除字段只是簡單的從架構(gòu)中刪除該字段 —— 索引不會變小,有關(guān)該字段的數(shù)據(jù)將保留在索引中,直到您進行優(yōu)化。優(yōu)化將壓縮索引,同時刪除對已刪除字段的引用:

writer = ix.writer()
writer.add_field("uuid", fields.ID(stored=True))
writer.remove_field("path")
writer.commit(optimize=True)

因為數(shù)據(jù)是以字段名存儲在磁盤上的,所以在沒有優(yōu)化中間索引的情況下,不要添加與已刪除字段同名的新字段:

writer = ix.writer()
writer.delete_field("path")
# 不要這樣做!?。?writer.add_field("path", fields.KEYWORD)

(Whoosh 的未來版本可能會自動防止此錯誤。)

動態(tài)字段

動態(tài)字段讓您可以將字段類型與任意 "glob"(包含*、?、/[abc] 等通配符的名稱)類型字段相匹配。

您可以使用 add() 方法將動態(tài)字段添加到 glob 關(guān)鍵字設(shè)置為 True 的新模式:

schema = fields.Schema(...)
# 任何以 "_d" 結(jié)尾的字段名,都將被存儲為 DATETIME 類型
schema.add("*_d", fields.DATETIME(stored=True), glob=True)

要在現(xiàn)有索引上設(shè)置動態(tài)字段,與添加常規(guī)字段相同,使用 IndexWriter.add_field 方法,但 glob 關(guān)鍵字參數(shù)需要設(shè)置為 True

writer = ix.writer()
writer.add_field("*_d", fields.DATETIME(stored=True), glob=True)
writer.commit()

要刪除動態(tài)字段,請對以 glob 作為名稱的字段使用 IndexWriter.remove_field() 方法 :

writer = ix.writer()
writer.remove_field("*_d")
writer.commit()

例如,要允許文檔包含以 _id 結(jié)尾的任何字段名稱并將其與 ID 字段類型相關(guān)聯(lián):

schema = fields.Schema(path=fields.ID)
schema.add("*_id", fields.ID, glob=True)

ix = index.create_in("myindex", schema)

w = ix.writer()
w.add_document(path=u"/a", test_id=u"alfa")
w.add_document(path=u"/b", class_id=u"MyClass")
# ...
w.commit()

qp = qparser.QueryParser("path", schema=schema)
q = qp.parse(u"test_id:alfa")
with ix.searcher() as s:
    results = s.search(q)

高級模式設(shè)置

字段提升 (Field boosts)

您可以為字段指定字段提升。這是一個乘數(shù),適用于在該字段中找到的任何術(shù)語的分數(shù)。例如,要使 title 字段中的術(shù)語得分是 body 字段中術(shù)語得分的兩倍:

schema = Schema(title=TEXT(field_boost=2.0), body=TEXT)

字段類型

上面列出的預(yù)定義字段類型是 fields.FieldType 的子類。 FieldType 是一個非常簡單的類。它的屬性包含定義字段行為的信息。

屬性 類型 描述
format fields.Format 定義字段記錄關(guān)于每個術(shù)語的信息類型,以及信息如何存儲在磁盤上。
vector fields.Format 可選:如果已定義,則為該字段存儲每個文檔的前向索引信息的格式。
scorable bool 如果為 True,則每個文檔中字段存儲在索引中的長度(術(shù)語的數(shù)量)。有點命名錯誤,因為字段長度不是所有評分所必需的。但是需要字段長度才能從 BM25F 獲得正確的結(jié)果。
stored bool 如果為 True,則此字段的值存儲在索引中。
unique bool 如果為 True,則當用戶在 IndexWriter 上調(diào)用 document_update() 時,此字段的值可用于替換具有相同值的文檔。

大多數(shù)預(yù)定義字段類型的構(gòu)造函數(shù)都具有可讓您自定義這些部分的參數(shù)。例如:

  • 大多數(shù)預(yù)定義的字段類型都可以在構(gòu)造函數(shù)中使用 FieldType.stored 參數(shù)。
  • TEXT() 構(gòu)造函數(shù)可以使用 analyzer 參數(shù)設(shè)置格式對象。

格式

對象 Format 定義字段記錄關(guān)于每個術(shù)語的信息類型,以及信息如何在磁盤上存儲。

例如,Existence 格式將存儲這樣的帖子 (postings):

Doc
10
20
30

Positions 格式將存儲這樣的帖子:

Doc Positions
10 [1,5,23]
20 [45]
30 [7,12]

索引代碼將字段的 unicode 字符串傳遞給字段的 Format 對象。該 Format 對象調(diào)用其分析器(請參閱文本分析)將字符串分解為標記,然后對有關(guān)每個標記的信息進行編碼。

Whoosh 附帶以下預(yù)定義格式。

類名 描述
Stored 存儲但未索引的字段的“null”格式。
Existence 只記錄詞是否在文檔中,而不存儲詞頻。對于標識符字段(例如路徑或 ID)和 “tag” 類型字段很有用,這些字段的頻率應(yīng)始終為 0 或 1
Frequency 存儲每個術(shù)語在每個文檔中出現(xiàn)的次數(shù)。
Positions 存儲每個術(shù)語在每個文檔中出現(xiàn)的次數(shù)以及出現(xiàn)的位置。

STORED 字段類型使用 Stored 格式(什么都不做,所以 STORED 字段沒有索引)。

類型 ID 使用 Existence 格式。

類型 KEYWORD 使用 Frequency 格式。

類型 TEXT 如果使用 phrase=True(默認值)實例化則使用 Positions 格式 ,如果 phrase=False 則使用 Frequency 格式.

此外,為方便專家用戶而實現(xiàn)了以下格式,但目前尚未在 Whoosh 中使用:

類名 描述
DocBoosts 與 Existence 類似,但額外存儲每個文檔的提升(boosts)
Characters 與 Positions 類似,但額外存儲每個術(shù)語的開始和結(jié)束字符索引
PositionBoosts 與 Positions 類似,但額外存儲每個位置的提升
CharacterBoosts 與 Positions 類似,但額外存儲每個術(shù)語和每個位置提升的開始和結(jié)束字符索引

向量

主索引是倒排索引。它將術(shù)語映射到它們出現(xiàn)的文檔。存儲前向索引(也稱為詞向量)有時也很有用,它將文檔映射到出現(xiàn)在其中的術(shù)語。

例如,想象一個字段的倒排索引:

Term Postings
apple [(doc=1, freq=2), (doc=2, freq=5), (doc=3, freq=1)]
bear [(doc=2, freq=7)]

相應(yīng)的前向索引或詞向量將是:

Doc Postings
1 [(text=apple, freq=2)]
2 [(text=apple, freq=5), (text='bear', freq=7)]
3 [(text=apple, freq=1)]

如果設(shè)置 FieldType.vector 為一個 Format 對象,索引代碼將使用該 Format 對象來存儲有關(guān)每個文檔中的術(shù)語的信息。目前默認情況下 Whoosh 根本不使用術(shù)語向量,但它們可供希望實現(xiàn)自己的字段類型的專家用戶使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容