您可以搜索这两种类型,但要搜索 MissingValue 条目需要自定义处理内部目录数据结构。
索引从一个对象中获取值,并索引它。如果存在AttributeError 或类似名称,则索引不存储该对象的任何内容,并且如果相同的字段是返回列的一部分,则在这种情况下,将给出MissingValue 以指示该索引为空字段。
在以下示例中,我假设您有一个变量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)