index_object:pairs()
Поиск кортежа или набора кортежей по указанному индексу с возможностью
перебирать их по одному кортежу за раз. Для поиска по первичному
индексу в указанном спейсе используйте метод box_space-pairs.
Параметр {key} задает, что должно совпадать в индексе.
Параметр {iterator} задает правило сопоставления и упорядочивания.
Разные типы индексов поддерживают разные итераторы. Например, индекс
TREE поддерживает строгий порядок ключей и может возвращать все кортежи
в порядке возрастания или убывания, начиная с указанного ключа. Другие
типы индексов, однако, не поддерживают упорядочивание.
Чтобы понять согласованность кортежей, возвращаемых итератором, важно
знать принципы работы подсистемы обработки транзакций Tarantool.
Итератор в Tarantool не владеет согласованным представлением чтения.
Вместо этого каждой процедуре предоставляется эксклюзивный доступ ко
всем кортежам и спейсам до тех пор, пока не произойдет "переключение
контекста", которое может случиться из-за
правил неявной передачи управления,
либо из-за явного вызова fiber.yield. Когда поток выполнения
возвращается к приостановленной процедуре, набор данных мог значительно
измениться. Итерация, возобновленная после точки передачи управления,
не сохраняет представление чтения, а продолжается с новым содержимым
базы данных. В руководстве
Индексированный поиск по шаблонам
показан один из способов совместного использования итераторов и
передачи управления.
Информацию о внутренней структуре итераторов см. в документации "Lua Functional library".
Параметры:
index_object(index_object) — ссылка на объект.key(scalar/table) — значение для сопоставления с ключом индекса, который может быть составным.iterator— как определено в таблицах ниже. Тип итератора по умолчанию — 'EQ'.after— кортеж или позиция кортежа (tuple_pos), после которогоpairsначинает поиск. Чтобы начать поиск с первого кортежа, передайте этому параметру пустую строку илиbox.NULL.
Возвращает
Итератор, который можно
использовать в цикле for/end или с функцией
totable().
Возможные ошибки:
- такого спейса не существует
- неверный тип
- выбранный тип итерации не поддерживается для данного типа индекса
- ключ не поддерживается для данного типа итерации
- недопустимая позиция итератора
Факторы сложности: Размер индекса, тип индекса; количество обрабатываемых кортежей.
Значение ключа поиска может быть числом (например 1234), строкой
(например 'abcd') или таблицей чисел и строк (например
{1234, 'abcd'}). Каждая часть ключа будет сравниваться с каждой
частью ключа индекса.
Возвращаемые кортежи будут упорядочены по значению ключа индекса, либо по хешу значения ключа индекса, если тип индекса — 'hash'. Если индекс неуникальный, дубликаты будут дополнительно упорядочены по значению первичного ключа. Порядок будет обратным, если тип итератора — 'LT', 'LE' или 'REQ'.
Тип итератора | Аргументы | Описание |
|---|---|---|
box.index.EQ или 'EQ' | искомое значение | Оператор сравнения — '==' (равно). Если ключ индекса равен искомому значению, он совпадает. Кортежи возвращаются в порядке возрастания по ключу индекса. Используется по умолчанию. |
box.index.REQ или 'REQ' | искомое значение | Сопоставление такое же, как для |
box.index.GT или 'GT' | искомое значение | Оператор сравнения — '>' (больше чем). Если ключ индекса больше искомого значения, он совпадает. Кортежи возвращаются в порядке возрастания по ключу индекса. |
box.index.GE или 'GE' | искомое значение | Оператор сравнения — '>=' (больше или равно). Если ключ индекса больше или равен искомому значению, он совпадает. Кортежи возвращаются в порядке возрастания по ключу индекса. |
box.index.ALL или 'ALL' | искомое значение | То же, что и box.index.GE. |
box.index.LT или 'LT' | искомое значение | Оператор сравнения — '<' (меньше чем). Если ключ индекса меньше искомого значения, он совпадает. Кортежи возвращаются в порядке убывания по ключу индекса. |
box.index.LE или 'LE' | искомое значение | | Оператор сравнения — '<=' (меньше или равно). Если ключ индекса меньше или равен искомому значению, он совпадает. Кортежи возвращаются в порядке убывания по ключу индекса. |
Неформально можно сказать, что поиск с помощью индексов TREE в целом интуитивно понятен пользователям, при условии отсутствия nil-значений и отсутствующих частей. Формально логика выглядит следующим образом:
- Ключ поиска содержит ноль или более частей, например
{},{1,2,3},{1,nil,3}. - Ключ индекса содержит одну или более частей, например
{1},{1,2,3},{1,2,3}. - Ключ поиска может содержать
nil(но неmsgpack.NULL, что является неверным типом). - Ключ индекса не может содержать
nilилиmsgpack.NULL, хотя в более поздней версии Tarantool правила могут отличаться — поведение поиска со значениемnilможет измениться. - Возможные итераторы: LT, LE, EQ, REQ, GE, GT.
- Считается, что ключ поиска "совпадает" с ключом индекса, если последующие утверждения, представляющие собой псевдокод операции сравнения, возвращают TRUE.
If (number-of-search-key-parts > number-of-index-key-parts) return ERRORIf (number-of-search-key-parts == 0) return TRUEfor (i = 1; ; ++i){if (i > number-of-search-key-parts) OR (search-key-part[i] is nil){if (iterator is LT or GT) return FALSEreturn TRUE}if (type of search-key-part[i] is not compatible with type of index-key-part[i]){return ERROR}if (search-key-part[i] == index-key-part[i]){continue}if (search-key-part[i] > index-key-part[i]){if (iterator is EQ or REQ or LE or LT) return FALSEreturn TRUE}if (search-key-part[i] < index-key-part[i]){if (iterator is EQ or REQ or GE or GT) return FALSEreturn TRUE}}
Тип итератора | Аргументы | Описание |
|---|---|---|
box.index.ALL или 'ALL' | нет | Совпадают все ключи индекса. Кортежи возвращаются в порядке возрастания по хешу ключа индекса, который будет выглядеть случайным. |
box.index.EQ или 'EQ' | искомое значение | Оператор сравнения — '==' (равно). Если ключ индекса равен искомому значению, он совпадает. Количество возвращаемых кортежей будет равно 0 или 1. Используется по умолчанию. |
Тип итератора | Аргументы | Описание |
|---|---|---|
Тип итератора | Аргументы | Описание |
box.index.ALL или 'ALL' | нет | Совпадают все ключи индекса. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.EQ или 'EQ' | битовое значение | Если ключ индекса равен битовому значению, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. Используется по умолчанию. |
box.index.BITS_ALL_SET | битовое значение | Если все биты, равные 1 в битовом значении, равны 1 в ключе индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.BITS_ANY_SET | битовое значение | Если любой из битов, равных 1 в битовом значении, равен 1 в ключе индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.BITS_ALL_NOT_SET | битовое значение | Если все биты, равные 1 в битовом значении, равны 0 в ключе индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
Тип итератора | Аргументы | Описание |
|---|---|---|
box.index.ALL или 'ALL' | нет | Совпадают все ключи. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.EQ или 'EQ' | искомое значение | Если все точки прямоугольника-или-куба, заданного искомым значением, совпадают с прямоугольником-или-кубом, заданным ключом индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. "Прямоугольник-или-куб" означает "прямоугольник-или-куб, как описано в разделе о :ref: |
box.index.GT или 'GT' | искомое значение | Если все точки прямоугольника-или-куба, заданного искомым значением, находятся внутри прямоугольника-или-куба, заданного ключом индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.GE или 'GE' | искомое значение | Если все точки прямоугольника-или-куба, заданного искомым значением, находятся внутри или на границе прямоугольника-или-куба, заданного ключом индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.LT или 'LT' | искомое значение | Если все точки прямоугольника-или-куба, заданного ключом индекса, находятся внутри прямоугольника-или-куба, заданного ключом поиска, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.LE или 'LE' | искомое значение | Если все точки прямоугольника-или-куба, заданного ключом индекса, находятся внутри или на границе прямоугольника-или-куба, заданного ключом поиска, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.OVERLAPS или 'OVERLAPS' | искомое значение | Если некоторые точки прямоугольника-или-куба, заданного искомым значением, находятся внутри прямоугольника-или-куба, заданного ключом индекса, он совпадает. Кортежи возвращаются в порядке их расположения в спейсе. |
box.index.NEIGHBOR или 'NEIGHBOR' | искомое значение | Если некоторые точки прямоугольника-или-куба, заданного ключом, находятся внутри или на границе прямоугольника-или-куба, заданного ключом индекса, он совпадает. Кортежи возвращаются в порядке: сначала ближайший сосед. |
Примеры:
Ниже приведено несколько примеров использования pairs с различными
параметрами. Чтобы попробовать эти примеры, необходимо выполнить
начальную загрузку базы данных Tarantool, как описано в
Использование операций с данными.
-- Вставка тестовых данных --tarantool> bands:insert{1, 'Roxette', 1986}bands:insert{2, 'Scorpions', 1965}bands:insert{3, 'Ace of Base', 1987}bands:insert{4, 'The Beatles', 1960}bands:insert{5, 'Pink Floyd', 1965}bands:insert{6, 'The Rolling Stones', 1962}bands:insert{7, 'The Doors', 1965}bands:insert{8, 'Nirvana', 1987}bands:insert{9, 'Led Zeppelin', 1968}bands:insert{10, 'Queen', 1970}---...-- Выборка всех кортежей по первичному индексу --tarantool> for _, tuple in bands.index.primary:pairs() doprint(tuple)end[1, 'Roxette', 1986][2, 'Scorpions', 1965][3, 'Ace of Base', 1987][4, 'The Beatles', 1960][5, 'Pink Floyd', 1965][6, 'The Rolling Stones', 1962][7, 'The Doors', 1965][8, 'Nirvana', 1987][9, 'Led Zeppelin', 1968][10, 'Queen', 1970]---...-- Выборка всех кортежей, значения вторичного ключа которых начинаются с указанной строки --tarantool> for _, tuple in bands.index.band:pairs("The", {iterator = "GE"}) doif (string.sub(tuple[2], 1, 3) ~= "The") then break endprint(tuple)end[4, 'The Beatles', 1960][7, 'The Doors', 1965][6, 'The Rolling Stones', 1962]---...-- Выборка всех кортежей, значения вторичного ключа которых находятся между 1965 и 1970 --tarantool> for _, tuple in bands.index.year:pairs(1965, {iterator = "GE"}) doif (tuple[3] > 1970) then break endprint(tuple)end[2, 'Scorpions', 1965][5, 'Pink Floyd', 1965][7, 'The Doors', 1965][9, 'Led Zeppelin', 1968][10, 'Queen', 1970]---...-- Выборка всех кортежей после указанного кортежа --tarantool> for _, tuple in bands.index.primary:pairs({}, {after={7, 'The Doors', 1965}}) doprint(tuple)end[8, 'Nirvana', 1987][9, 'Led Zeppelin', 1968][10, 'Queen', 1970]---...