Выбор из Tarantool по составному индексу с разными итераторами

У меня есть пространство народы:

  1. id
  2. имя
  3. возраст

с двумя индексами:

peoples = box.schema.space.create('peoples', {engine = 'memtx', field_count = 3, if_not_exists = true})
peoples:create_index('primary', {type = 'TREE', unique = true, parts = {1, 'unsigned'}, if_not_exists = true})
peoples:create_index('by_name_age', {type = 'TREE', unique = false, parts = {2, 'STR', 3, 'unsigned'}, if_not_exists = true})

и с данными:

peoples:auto_increment{ 'name_1', 10 }
peoples:auto_increment{ 'name_1', 11 }
peoples:auto_increment{ 'name_1', 12 }

Мне нужно отбирать народы по имени и возрасту больше, чем какое-то значение. Например, я хочу выделить всех «Alex» с возрастом> 10, ожидая следующего результата:

[1, 'Alex', 11]
[2, 'Alex', 12]

Пытаюсь выполнить запрос:

peoples.index.by_name_age:select({'Alex', 10}, {{iterator = box.index.EQ},{iterator = box.index.GT}})

но получить результат

[1, 'Alex', 10]

Как я могу использовать разные итераторы для частей индекса имени и возраста?


person andrey_ustinov    schedule 21.03.2018    source источник


Ответы (2)


У вас есть индекс, отсортированный по первой части. Означает, что он не может сделать выбор, как вы ожидаете.

Что нужно сделать, чтобы увидеть ожидаемое поведение? Вы должны использовать цикл for [1] с итератором GE, и вы должны тестировать диапазоны, используя условие if внутри этого цикла.

[1] Простой пример кода:

local test_val = 'Alex'
for _, v in peoples.index.by_name_age:select({test_val, 10}, {iterator = box.index.GE})
   if v[1] ~= test_val then
   -- do exit
   end
   -- do store result 
end
person Vasiliy Soshnikov    schedule 22.03.2018
comment
Спасибо, Василий! - person andrey_ustinov; 22.03.2018

peoples.index.by_name_age:pairs({'Alex', 10}, 'GE'):
    take_while(function(x) return x.name == 'Alex' end):
    totable()

Здесь он начинает перебирать все записи с name >= 'Alex' and age >= 10. take_while используется для ограничения записей только совпадением name == 'Alex'.

:totable() не является обязательным, без него это выражение можно использовать в цикле for аналогично pairs.

person prcu    schedule 03.09.2019