设计模式¶
关于架构和字段¶
模式指定索引中文档的字段。
每个文档可以有多个字段,如标题、内容、URL、日期等。
一些字段可以被索引,一些字段可以与文档一起存储,这样字段值在搜索结果中可用。某些字段将同时被索引和存储。
模式是文档中所有可能字段的集合。每个单独的文档可能只使用模式中可用字段的子集。
例如,用于为电子邮件编制索引的简单模式可能具有如下字段 from_addr
, to_addr
, subject
, body
和 attachments
那里 attachments
field lists the names of attachments to the email. For emails without attachments, you would omit the attachments field.
内置字段类型¶
whoosh提供了一些有用的预定义字段类型:
whoosh.fields.TEXT
此类型用于正文文本。它索引(并可选地存储)文本并存储术语位置,以允许短语搜索。
TEXT
字段使用StandardAnalyzer
默认情况下。要指定其他分析器,请使用analyzer
构造函数的关键字参数,例如TEXT(analyzer=analysis.StemmingAnalyzer())
. 见 关于分析器 .默认情况下,
TEXT
字段存储每个索引项的位置信息,以允许您搜索短语。如果不需要在文本字段中搜索短语,可以关闭存储术语位置以节省空间。使用TEXT(phrase=False)
.默认情况下,
TEXT
不存储字段。通常,您不希望在搜索索引中存储正文文本。通常,索引文档本身可以根据搜索结果进行读取或链接,因此不需要将它们的文本存储在搜索索引中。但是,在某些情况下,它是有用的(参见 如何创建突出显示的搜索结果摘要 )使用TEXT(stored=True)
指定文本应存储在索引中。whoosh.fields.KEYWORD
此字段类型是为空格或逗号分隔的关键字设计的。此类型是可索引和搜索的(并且可以选择存储)。为了节省空间,它不支持短语搜索。
要将字段值存储在索引中,请使用
stored=True
在构造函数中。要在索引关键字之前自动将其小写,请使用lowercase=True
.默认情况下,关键字是空格分隔的。要用逗号分隔关键字(允许包含空格的关键字),请使用
commas=True
.如果用户将使用关键字字段进行搜索,请使用
scorable=True
.whoosh.fields.ID
这个
ID
字段类型只是将字段的整个值作为一个单元进行索引(并可选地存储)(也就是说,它不会将字段分解为单个术语)。这种类型的字段不存储频率信息,所以它非常紧凑,但对于评分来说不是很有用。使用
ID
对于url或path(文档的url或文件路径)、date、category等字段,这些字段的值必须作为一个整体来处理,并且每个文档的字段只有一个值。默认情况下,
ID
不存储字段。使用ID(stored=True)
指定字段值应与文档一起存储,以便在搜索结果中使用。例如,您希望存储URL字段的值,以便在搜索结果中提供指向原始字段的链接。whoosh.fields.STORED
此字段与文档一起存储,但未编入索引且不可搜索。这对于要在搜索结果中显示给用户的文档信息很有用,但不需要能够搜索。
whoosh.fields.NUMERIC
此字段以紧凑、可排序的格式存储int、long或浮点数字。
whoosh.fields.DATETIME
此字段以紧凑的可排序格式存储日期时间对象。
whoosh.fields.BOOLEAN
这个简单的文件索引了布尔值并允许用户搜索
yes
,no
,true
,false
,1
,0
,t
或f
.whoosh.fields.NGRAM
TBD。
专家用户可以创建自己的字段类型。
创建架构¶
创建架构:
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)
如果没有为某个预定义字段指定任何构造函数关键字参数,则可以不使用括号(例如 fieldname=TEXT
而不是 fieldname=TEXT()
)whoosh将为您实例化类。
或者,可以使用 SchemaClass
基类::
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
实例。
索引后修改架构¶
创建索引后,可以使用 add_field()
和 remove_field()
方法。这些方法在 Writer
对象:
writer = ix.writer()
writer.add_field("fieldname", fields.TEXT(stored=True))
writer.remove_field("content")
writer.commit()
(如果要修改模式 and 使用相同的编写器添加文档,必须调用 add_field()
和/或 remove_field
before 您可以添加任何文档。)
这些方法也适用于 Index
对象作为方便,但当您在 Index
,index对象只创建编写器,对其调用相应的方法并提交,因此如果要添加或删除多个字段,则自己创建编写器的效率会更高:
ix.add_field("fieldname", fields.KEYWORD)
在 filedb
后端,删除字段只需从 schema --索引将不会变小,有关该字段的数据将保留在索引中,直到优化为止。优化将压缩索引,同时删除对已删除字段的引用::
writer = ix.writer()
writer.add_field("uuid", fields.ID(stored=True))
writer.remove_field("path")
writer.commit(optimize=True)
因为数据以字段名存储在磁盘上, do not 添加与已删除字段同名的新字段,而不优化以下两者之间的索引:
writer = ix.writer()
writer.delete_field("path")
# Don't do this!!!
writer.add_field("path", fields.KEYWORD)
(未来版本的whoosh可能会自动防止此错误。)
动态场¶
动态字段允许您将字段类型与任何与给定“glob”(包含 *
, ?
和/或 [abc]
通配符)。
您可以使用 add()
方法与 glob
keyword set to True:
schema = fields.Schema(...)
# Any name ending in "_d" will be treated as a stored
# DATETIME field
schema.add("*_d", fields.DATETIME(stored=True), glob=True)
要在现有索引上设置动态字段,请使用相同的 IndexWriter.add_field
方法,就像添加常规字段一样,但使用 glob
关键字参数设置为 True
::
writer = ix.writer()
writer.add_field("*_d", fields.DATETIME(stored=True), glob=True)
writer.commit()
要删除动态字段,请使用 IndexWriter.remove_field()
方法的名称为glob::
writer = ix.writer()
writer.remove_field("*_d")
writer.commit()
例如,允许文档包含以 _id
并将其与 ID
字段类型:
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)
高级架构设置¶
场升压¶
可以为字段指定字段增强。这是一个乘数,适用于在该字段中找到的任何术语的分数。例如,要使标题字段中的术语得分是正文字段中术语的两倍,请执行以下操作:
schema = Schema(title=TEXT(field_boost=2.0), body=TEXT)
字段类型¶
上面列出的预定义字段类型是 fields.FieldType
. FieldType
是一个非常简单的类。其属性包含定义字段行为的信息。
属性 |
类型 |
描述 |
---|---|---|
格式 |
fields.Format |
定义字段记录每个术语的信息类型,以及信息存储在磁盘上的方式。 |
矢量 |
fields.Format |
可选:如果已定义,则存储此字段的每个文档转发索引信息的格式。 |
可评分的 |
布尔 |
如果为真,则每个文档中字段的长度(字数)存储在索引中。有点误称,因为并非所有评分都需要字段长度。但是,要从BM25F获得正确的结果,需要字段长度。 |
存储 |
布尔 |
如果为真,则此字段的值存储在索引中。 |
独特的 |
布尔 |
如果为true,则当用户调用时,此字段的值可用于替换具有相同值的文档。 |
大多数预定义字段类型的构造函数都有参数,您可以通过这些参数自定义这些部分。例如:
大多数预定义的字段类型都采用设置fieldType.stored的存储关键字参数。
这个
TEXT()
构造函数接受analyzer
传递给格式化对象的关键字参数。
格式¶
A Format
对象定义字段记录每个术语的信息类型,以及信息存储在磁盘上的方式。
例如, Existence
格式将存储这样的日志:
doc |
|
---|---|
10 |
|
20 |
|
30 |
鉴于 Positions
格式将存储这样的日志:
doc |
位置 |
---|---|
10 |
|
20 |
|
30 |
|
索引代码将字段的Unicode字符串传递给字段的 Format
对象。这个 Format
对象调用其分析器(请参阅文本分析)将字符串拆分为标记,然后对每个标记的信息进行编码。
whoosh提供以下预先定义的格式。
类名 |
描述 |
---|---|
存储 |
存储但未编入索引的字段的“空”格式。 |
存在 |
只记录术语是否在文档中,即不存储术语频率。对于标识符字段(如路径或ID)和“tag”类型字段很有用,其中频率应始终为0或1。 |
频率 |
存储每个术语在每个文档中出现的次数。 |
位置 |
存储每个术语在每个文档中出现的次数,以及出现在哪个位置。 |
这个 STORED
字段类型使用 Stored
格式(什么都不做,所以 STORED
字段没有索引)。这个 ID
类型使用 Existence
格式。这个 KEYWORD
类型使用 Frequency
格式。这个 TEXT
类型使用 Positions
如果它被实例化为 phrase=True
(违约),或 Frequency
如果 phrase=False
.
此外,为了方便专家用户,还实施了以下格式,但目前并未在whoosh中使用:
类名 |
描述 |
---|---|
DocBoosts |
就像存在一样,但每个文档的存储量也会增加 |
文字 |
与位置相同,但也存储每个术语的开始和结束字符索引 |
PositionBoosts |
像 Positions ,但也存储每个位置的提升 |
CharacterBoosts |
与位置类似,但也存储每个术语和每个位置提升的开始和结束字符索引 |
向量¶
主索引是反向索引。它将术语映射到它们出现的文档中。有时存储向前索引(也称为术语向量)也很有用,它将文档映射到文档中出现的术语。
例如,假设一个字段的倒排索引如下:
术语 |
帖子 |
---|---|
苹果 |
|
熊 |
|
相应的正向指数或术语向量为:
doc |
帖子 |
---|---|
1 |
|
2 |
|
3 |
|
如果你设置 FieldType.vector
到A Format
对象,索引代码将使用 Format
对象来存储每个文档中有关术语的信息。目前,默认情况下,whoosh根本不使用术语向量,但对于希望实现自己字段类型的专家用户,它们是可用的。