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,将对象调进内存里。

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。通常用于按路径和路径深度条件来搜索内容。
添加新的Indexs 和metadata 列
当一个对象被索引时,这个 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添加三个索引。其中两个将提供值为 startend 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, 一个工作流状态
另外,搜索结果可以基于FieldIndex, KeywordIndex or DateIndex 索引用下面的关键词参数来进行排序:
  • 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类型
关于 catalog 索引和搜索的更多详细信息参考: ZCatalog chapter in the Zope 2 book.
设置