模式設(shè)計
關(guān)于模式和字段
模式指定索引中文檔的字段悔橄。
每個文檔可以有多個字段,比如標題腺毫、內(nèi)容、url挣柬、日期等潮酒。
一些字段可以被索引,一些字段可以與文檔一起存儲邪蛔,以便字段值在搜索結(jié)果中可用急黎。一些字段將被索引和存儲。
模式是文檔中所有可能字段的集合侧到。每個單獨的文檔可能只使用模式中可用字段的一個子集勃教。
例如,用于索引電子郵件的簡單模式可能包含 from_addr
匠抗、to_addr
故源、subject
、body
和 attachments
等字段 汞贸,其中 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
,t
或 f
蔚润。
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
對象上,但是當(dāng)您在 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")
# 不要這樣做;i佘浴!
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 八拱,則當(dāng)用戶在 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)自己的字段類型的專家用戶使用。