Dexterity开发手册:第六章 第12节 catalog索引策略
Dexterity开发手册:第六章 第12节 catalog索引策略
http://www.315ok.org/blogfolder/406
http://www.315ok.org/logo.png
Dexterity开发手册:第六章 第12节 catalog索引策略
Dexterity开发手册:第六章 第12节 catalog索引策略
Catalog 索引策略
本文主要探讨怎样建立定制的catalog索引
ZODB是一个分层的对象数据库,可以存储不同schematade 对象。这个特性对于管理独立的内容对象非常好。但是对于跨内容存储路径的搜索,没有优化。一个简单的搜索,需要遍历整个对象存储图,针对搜索准则,逐一将对象调入内存,比较对象的原数据,在一个较大的网站,这将很快使得网站瘫痪
幸运的是,Zope自带有一个ZCatalog技术——为搜索功能建立一个基本的优化的表结构。在Plone 中, 这种ZCatalog的实例对象叫 portal_catalog.。在Plone系统中有很多标准的事件机制来保证站点中任何对象被创建、修改是被自动建立索引,被删除时,自动删除索引。
这个catalog管理的索引能被用来搜索,在catalog中还有大量元数据,这些元数据是对象的部分被拷贝到catalog的属性。当我们执行一个搜索时,结构返回一个catalog brains。catalog brains包含各种metadata列作为属性的值。函数 getURL(), getPath() 和 getObject() 可以取得被索引对象的 URL 和 path,将对象调进内存里。
当一个对象被索引时,这个 catalog 将试图发现该对象的匹配index和column名的属性和方法,如果能发现一个值,该值即被索引。
下面的例子我们来索引session的track属性,为这个属性加一个元数据 column:
创建定制的索引器(Ceating custom indexers)
基于属性的索引某些时候满足不了特别要求。首先这个catalog不加区别地试图为每一个对象索引所有列出的元数据。其次,要加一个计算索引值的方法或属性到一个类并不总是可行。 Plone 在3.3版以后增加了一个系统包叫 plone.indexer ,可以用来写定制的索引器。 components that are invoked to calculate the value the catalog sees when it tries to index a given attribute. Indexers can be used to index a different value to the one stored on the object, or to allow indexing of a "virtual" attribute that does not actually exist on the object is question. Indexers 通常被基于内容类型来注册,因此对不同的内容类型,你可以有不同的索引实现。
为举例说明indexers, 我们将为 program.py添加三个索引。其中两个将提供值为 start 和 end indexes, 这两个索引默认是为系统的 Event 类型注册的。 第三个索引器将为 Subject index提供一个值,这个值来自Tracks list。
一旦我们注册了自己的索引,并通过重新安装产品来激活该索引,我们就能象使用系统缺省索引一样来使用我们自定义的索引,下面是样例:
本文主要探讨怎样建立定制的catalog索引
ZODB是一个分层的对象数据库,可以存储不同schematade 对象。这个特性对于管理独立的内容对象非常好。但是对于跨内容存储路径的搜索,没有优化。一个简单的搜索,需要遍历整个对象存储图,针对搜索准则,逐一将对象调入内存,比较对象的原数据,在一个较大的网站,这将很快使得网站瘫痪
幸运的是,Zope自带有一个ZCatalog技术——为搜索功能建立一个基本的优化的表结构。在Plone 中, 这种ZCatalog的实例对象叫 portal_catalog.。在Plone系统中有很多标准的事件机制来保证站点中任何对象被创建、修改是被自动建立索引,被删除时,自动删除索引。
这个catalog管理的索引能被用来搜索,在catalog中还有大量元数据,这些元数据是对象的部分被拷贝到catalog的属性。当我们执行一个搜索时,结构返回一个catalog brains。catalog brains包含各种metadata列作为属性的值。函数 getURL(), getPath() 和 getObject() 可以取得被索引对象的 URL 和 path,将对象调进内存里。
Dexterity 对象比Archetypes对象更轻量级。这意味着调入对象到内存时,消耗的资源更少。直接调入对象入内存是在你采用引用、父对象、小规模的子对象时,可以采用,然而,当有不可知的大量对象时,不建议采用对象直接调入内存的方法,而应该采用catalog搜索功能来找到他们,并将要经常访问的属性用catalog metadata保存起来,然后通过搜索得来的brains来访问这些属性。通常情况下大的字符串(如一个文档的body text)或者二进制数据应避免保存为catalog metadat。Plone 本身有大量的标准 indexes和 metadata columns。这些使得访问主要的 Dublin Core set 的 metadata和访问plone特别的属性一样方便。你可以通过ZMI的portal_catalog工具查看索引和元数据以及被索引的内容。 索引有如下几种类型:
- FieldIndex, 最通常的类型,用于索引单个值。
- KeywordIndex, 用于索引序列值(lists),可以用于搜索这个lists的一个子集,通常用在 keyword 字段,Subject Dublin Core metadata 字段
- DateIndex, 用于索引Zope 2 DateTime 对象。注意如果你定义一个 Python datetime object,需要将其转换为 Zope 2 DateTime ,通常可以采用定制的indexer来实现。
- DateRangeIndex, 主要用于有效的日期范围。
- ZCTextIndex, 主要用于SearchableText 索引。通常用于全文索引搜索。
- ExtendedPathIndex, PathIndex的一个扩展,用于 path index。通常用于按路径和路径深度条件来搜索内容。
当一个对象被索引时,这个 catalog 将试图发现该对象的匹配index和column名的属性和方法,如果能发现一个值,该值即被索引。
对象被索引时,被获取机制包装,这意味着一个索引值可以从父对象获取。然而,这也容易引起混淆,尤其当你建立容器内容类型,并为其建立新的索引时。如果,该容器的子对象没有和父亲对象同样的属性和方法,这个父亲对象的值将作为所有子对象的值被索引。Catalog indexes and metadata可以通过catalog.xml GenericSetup 导入方法来配置和安装。推荐参考 (parts/omelette/Products/CMFPlone/profiles/default/catalog.xml).
下面的例子我们来索引session的track属性,为这个属性加一个元数据 column:
<?xml version="1.0"?>
<object name="portal_catalog">
<index name="track" meta_type="FieldIndex">
<indexed_attr value="track"/>
</index>
<column value="track"/>
</object>注意:我们如何指定索引的名称和被索引的属性名称。有可能索引名称不同于被索引的属性名称,尽管这两个往往是相同的。这个 metadata 列仅仅是一个属性的名称。 创建定制的索引器(Ceating custom indexers)
基于属性的索引某些时候满足不了特别要求。首先这个catalog不加区别地试图为每一个对象索引所有列出的元数据。其次,要加一个计算索引值的方法或属性到一个类并不总是可行。 Plone 在3.3版以后增加了一个系统包叫 plone.indexer ,可以用来写定制的索引器。 components that are invoked to calculate the value the catalog sees when it tries to index a given attribute. Indexers can be used to index a different value to the one stored on the object, or to allow indexing of a "virtual" attribute that does not actually exist on the object is question. Indexers 通常被基于内容类型来注册,因此对不同的内容类型,你可以有不同的索引实现。
为举例说明indexers, 我们将为 program.py添加三个索引。其中两个将提供值为 start 和 end indexes, 这两个索引默认是为系统的 Event 类型注册的。 第三个索引器将为 Subject index提供一个值,这个值来自Tracks list。
from DateTime import DateTime
from plone.indexer import indexer
...
@indexer(IProgram)
def startIndexer(obj):
if obj.start is None:
return None
return DateTime(obj.start.isoformat())
grok.global_adapter(startIndexer, name="start")
@indexer(IProgram)
def endIndexer(obj):
if obj.end is None:
return None
return DateTime(obj.end.isoformat())
grok.global_adapter(endIndexer, name="end")
@indexer(IProgram)
def tracksIndexer(obj):
return obj.tracks
grok.global_adapter(tracksIndexer, name="Subject")这儿,我们用@indexer decorator 创建一个索引器。这个语法并不注册索引器部件,因此我们需要用 grok.global_adapter() 来完成注册,第一个参数是被定义的索引的名称,第二个参数是被索引的属性的名称,该属性将为该索引提供一个值。 由于所有这些索引器是标准Plone系统里已有的,我们不需要再在catalog.xml中重新注册。如果你创建定制的索引器,你需要在catalog.xml中注册 indexes 或 columns,记住这个 "indexed attribute" 名称 (以及the column 名称) 必须完全匹配在他的适配器注册中指定的名称。用自建的索引进行搜索Searching using your indexes
一旦我们注册了自己的索引,并通过重新安装产品来激活该索引,我们就能象使用系统缺省索引一样来使用我们自定义的索引,下面是样例:
from Products.CMFCore.utils import getToolByName
# get the tool
catalog = getToolByName(context, 'portal_catalog')
# execute a search
results = catalog(track='Track 1')
# examine the results
for brain in results:
start = brain.start
url = brain.getURL()
obj = brain.getObject() # Performance hit!一些常用索引:- Title, 对象的标题。
- Description, 对象的描述。
- path, 对象的路径。
- object_provides, 用于匹配该对象提供的接口。参数是一个接口名称或接口名称的列表。为了获取给点接口的名称,可以采用ISomeInterface.__identifier__.
- portal_type, 用于匹配portal类型。
- SearchableText, 用于全文搜索,支持象 AND 和 OR 这样的搜索条件在搜索字符串中。
- Creator, 一个内容创建者的名称
- Subject, a KeywordIndex of object keywords
- review_state, 一个工作流状态
- Use sort_on='<index name>' 按照特点的索引排序。例如, sort_on='sortable_title' 将生成一个基于标题的排序。 sort_on='Date' 将生成一个按发布日期或创建日期的排序。
- Add sort_order='reverse' 指明反向排序。缺省设置是 sort_order='ascending'. 'descending' 是r 'reverse'方式的别名。
- Add sort_limit=10 限制大约10个搜索结果。 Note that it is possible to get more results due to index optimisations. 在搜索结果上应用一个list切片时,应当确保返回的结果数量大于或等于你指定的限制参数。如: results = catalog(…, sort_limit=10)[:10]. 注意在使用 sort_limit 时,要求一个 sort_on 配合。
- Creator, 创建该内容的用户
- Date, 发布日期或创建日期(更后者优先)
- Title, 对象的标题
- Description, 对象的描述
- getId, 对象的id(注意这是一个属性,而不是一个函数)
- review_state, 对象的工作流状态
- portal_type, 对象的portal类型