Вы можете выполнять поиск по обоим типам, но для поиска записей 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
возвращает набор идентификаторов каталога IISet и его длину; каждый является указателем на запись каталога, для которой в именованном индексе нет записи. Затем вы можете использовать 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)
person
Martijn Pieters
schedule
27.06.2012