4

我想对缺少索引键值的对象的 zope 目录执​​行搜索。是否可以?

例如考虑以下代码行:

from Products.CMFCore.utils import getToolByName
catalog = getToolByName(context, 'portal_catalog')
results = catalog.searchResults({'portal_type': 'Event', 'review_state': 'pending'})

如果我对未插入某个项目而不是 portal_type 或 review_state 的对象感兴趣,该怎么办?

4

2 回答 2

7

您可以搜索这两种类型,但搜索MissingValue条目需要自定义处理内部目录数据结构。

索引从对象中获取值,并为其编制索引。如果有AttributeError或类似的,索引不存储该对象的任何内容,并且如果相同的字段是返回列的一部分,在这种情况下,MissingValue将给出 a 以指示该字段的索引为空。

在以下示例中,我假设您有一个catalog指向站点的 portal_catalog 工具的变量;例如getToolByName(context, 'portal_catalog')或类似的结果。

搜索无

您可以在许多索引中搜索None 就好了:

catalog(myKeywordIndex=None)

问题是大多数索引类型都忽略None了一个值。因此,搜索None将在日期和路径索引上失败;他们忽略索引上的 None 和布尔索引;他们在索引时将 None 变为 False。

关键字索引None也会忽略,除非它是序列的一部分。如果索引方法返回[None],它会很高兴被索引,但None它自己不会。

字段索引确实存储None在索引中。

请注意,每个索引都可以显示唯一值,因此您可以None通过调用来检查给定索引是否存储了值:

catalog.uniqueValuesFor(indexname)

搜索缺失值

这有点棘手。例如,每个索引都会跟踪它已索引的对象,以便能够在删除对象时从索引中删除数据。同时,目录会跟踪它作为一个整体索引的对象。

因此,我们可以计算这两组信息之间的差异。当您调用已发布的 API 时,目录一直都是这样做的,但是对于这个技巧,没有这样的公共 API。我们需要进入目录内部并为自己获取这些集合。

幸运的是,这些都是 BTree 集合,因此操作相对高效。这是我的做法:

from BTrees.IIBTree import IISet, difference

def missing_entries_for_index(catalog, index_name):
    # Return the difference between catalog and index ids
    index = catalog._catalog.getIndex(index_name)
    referenced = IISet(index.referencedObjects()) # Works with any UnIndex-based index
    return (
        difference(IISet(catalog._catalog.paths), referenced),
        len(catalog) - len(referenced)
    )

missing_entries_for_index方法返回目录 ID 的 IISet 及其长度;each 是指向指定索引没有条目的目录记录的指针。然后,您可以使用catalog.getpath将其转换为对象的完整路径,或用于catalog.getMetadataForRID获取元数据值的字典,或用于catalog.getobject获取原始对象本身,或用于catalog._catalog[]获取目录大脑。

以下方法将为您提供目录结果集,就像您从常规目录搜索中获得的一样:

from ZCatalog.Lazy import LazyMap

def not_indexed_results(catalog, index_name):
    rs, length = missing_entries_for_index(catalog, index_name)
    return LazyMap(catalog._catalog.__getitem__, rs.keys(), length)
于 2012-06-27T10:24:16.813 回答
0

谢谢前。实际上阅读您建议的链接,我发现没有技巧是不可能的。我从 pypi 报告:

请注意,对索引的负过滤仍将项目限制为在索引中具有值的项目。因此,对于 10 个文档,其中 5 个在 foo 索引中,值为 1,对 not 1 的查询将不返回任何项目,而不是返回 5 个没有值的项目。如果要考虑特定索引的所有项目,则需要索引一个虚拟/默认值。

所以有必要给你的项目一个默认值并寻找它。

于 2012-06-27T07:34:06.577 回答