Документация на русском языке
поддерживается сообществом

Примеры

Функция ниже проиллюстрирует, как обращаться ко всем спейсам, и для каждого отобразит примерное количество кортежей и первое поле первого кортежа. В данной функции используются функции из box.space в Tarantool’е: len() и pairs(). Итерация по спейсам закодирована в форме сканирования системного спейса _space, который содержит метаданные. Третье поле в _space содержит имя спейса, поэтому ключевая команда space_name = v[3] означает, что space_name – это поле space_name в кортеже _space, который мы только что получили с помощью pairs(). Функция возвращает таблицу:

function example() local tuple_count, space_name, line local ta = {} for k, v in box.space._space:pairs() do space_name = v[3] if box.space[space_name].index[0] ~= nil then tuple_count = '1 or more' else tuple_count = '0' end line = space_name .. ' tuple_count =' .. tuple_count if tuple_count == '1 or more' then for k1, v1 in box.space[space_name]:pairs() do line = line .. '. first field in first tuple = ' .. v1[1] break end end table.insert(ta, line) end return ta end 

А вот что происходит, когда вызывается функция:

tarantool> example() --- - - _schema tuple_count =1 or more. first field in first tuple = cluster - _space tuple_count =1 or more. first field in first tuple = 272 - _vspace tuple_count =1 or more. first field in first tuple = 272 - _index tuple_count =1 or more. first field in first tuple = 272 - _vindex tuple_count =1 or more. first field in first tuple = 272 - _func tuple_count =1 or more. first field in first tuple = 1 - _vfunc tuple_count =1 or more. first field in first tuple = 1 - _user tuple_count =1 or more. first field in first tuple = 0 - _vuser tuple_count =1 or more. first field in first tuple = 0 - _priv tuple_count =1 or more. first field in first tuple = 1 - _vpriv tuple_count =1 or more. first field in first tuple = 1 - _cluster tuple_count =1 or more. first field in first tuple = 1 ... 

Основная цель – отобразить имена и типы полей системного спейса, то есть использование метаданных для поиска метаданных.

Для начала: как можно сделать выборку кортежа из _space, который описывает _space?

Проще всего проверить постоянные в box.schema, что укажет на наличие элемента под названием SPACE_ID == 288. Таким образом, следующие запросы вернут нужный кортеж:

box.space._space:select{ 288 } -- или -- box.space._space:select{ box.schema.SPACE_ID } 

Также можно обратиться к спейсам в box.space._index, что укажет на наличие вторичного индекса с именем „name“ для спейса под номером 288. Таким образом, следующий запрос также вернет нужный кортеж:

box.space._space.index.name:select{ '_space' } 

Однако непросто прочитать информацию из полученного кортежа:

tarantool> box.space._space.index.name:select{'_space'} --- - - [280, 1, '_space', 'memtx', 0, {}, [{'name': 'id', 'type': 'num'}, {'name': 'owner', 'type': 'num'}, {'name': 'name', 'type': 'str'}, {'name': 'engine', 'type': 'str'}, {'name': 'field_count', 'type': 'num'}, {'name': 'flags', 'type': 'str'}, { 'name': 'format', 'type': '*'}]] ... 

Информация подается бессистемно, поскольку по формату поле №7 содержит рекомендованные имена и типы данных. Как же получить эти данные? Поскольку очевидно, что поле №7 представляет собой ассоциативный массив, цикл for проведет организацию данных:

tarantool> do  >  local tuple_of_space = box.space._space.index.name:get{'_space'}  >  for _, field in ipairs(tuple_of_space[7]) do  >  print(field.name .. ', ' .. field.type)  >  end  > end id, num owner, num name, str engine, str field_count, num flags, str format, * --- ... 

Пример ниже иллюстрирует все возможные сценарии – а также типичные ошибки – для всех операций с данными в Tarantool’е: INSERT, DELETE, UPDATE, UPSERT, REPLACE и SELECT.

-- Настройка базы данных -- box.cfg{} format = {} format[1] = {'field1', 'unsigned'} format[2] = {'field2', 'unsigned'} format[3] = {'field3', 'unsigned'} s = box.schema.create_space('test', {format = format}) -- Создание первичного индекса -- pk = s:create_index('pk', {parts = {{'field1'}}}) -- Создание уникального вторичного индекса -- sk_uniq = s:create_index('sk_uniq', {parts = {{'field2'}}}) -- Создание неуникального вторичного индекса -- sk_non_uniq = s:create_index('sk_non_uniq', {parts = {{'field3'}}, unique = false}) 

Операция insert (вставка) работает с кортежами с четким форматом и проверяет все ключи на наличие совпадений.

tarantool> -- Уникальные индексы: разрешено -- tarantool> s:insert({1, 1, 1}) --- - [1, 1, 1] ... tarantool> -- Конфликт первичного ключа: ошибка -- tarantool> s:insert({1, 1, 1}) --- - error: Duplicate key exists in unique index 'pk' in space 'test' ... tarantool> -- Конфликт уникального вторичного ключа: ошибка -- tarantool> s:insert({2, 1, 1}) --- - error: Duplicate key exists in unique index 'sk_uniq' in space 'test' ... tarantool> -- Ключ {1} присутствует в индексе sk_non_uniq, но он не уникален: разрешено -- tarantool> s:insert({2, 2, 1}) --- - [2, 2, 1] ... tarantool> s:truncate() --- ... 

delete (удаление) работает с полными ключами любого уникального индекса.

space:delete – это псевдоним для операции «удалить по первичному ключу».

tarantool> -- Вставить некоторые тестовые данные -- tarantool> s:insert{3, 4, 5} --- - [3, 4, 5] ... tarantool> s:insert{6, 7, 8} --- - [6, 7, 8] ... tarantool> s:insert{9, 10, 11} --- - [9, 10, 11] ... tarantool> s:insert{12, 13, 14} --- - [12, 13, 14] ... tarantool> -- Здесь ничего не происходит: нет ключа {4} в индексе pk -- tarantool> s:delete{4} --- ... tarantool> s:select{} --- - - [3, 4, 5] - [6, 7, 8] - [9, 10, 11] - [12, 13, 14] ... tarantool> -- Удалить по первичному ключу: разрешено -- tarantool> s:delete{3} --- - [3, 4, 5] ... tarantool> s:select{} --- - - [6, 7, 8] - [9, 10, 11] - [12, 13, 14] ... tarantool> -- Точно удалить по первичному ключу: разрешено -- tarantool> s.index.pk:delete{6} --- - [6, 7, 8] ... tarantool> s:select{} --- - - [9, 10, 11] - [12, 13, 14] ... tarantool> -- Удалить по уникальному вторичному ключу: разрешено -- s.index.sk_uniq:delete{10} --- - [9, 10, 11] ... s:select{} --- - - [12, 13, 14] ... tarantool> -- Удалить по неуникальному вторичному индексу: ошибка -- tarantool> s.index.sk_non_uniq:delete{14} --- - error: Get() doesn't support partial keys and non-unique indexes ... tarantool> s:select{} --- - - [12, 13, 14] ... tarantool> s:truncate() --- ... 

Ключ должен быть полным: операция delete не работает с компонентами ключа.

tarantool> s2 = box.schema.create_space('test2') --- ... tarantool> pk2 = s2:create_index('pk2', {parts = {{1, 'unsigned'}, {2, 'unsigned'}}}) --- ... tarantool> s2:insert{1, 1} --- - [1, 1] ... tarantool> -- Удалить по компоненту ключа: ошибка -- tarantool> s2:delete{1} --- - error: Invalid key part count in an exact match (expected 2, got 1) ... tarantool> -- Удалить по ключу целиком: разрешено -- tarantool> s2:delete{1, 1} --- - [1, 1] ... tarantool> s2:select{} --- - [] ... tarantool> s2:drop() --- ... 

Как и delete, update работает с полными ключами любого уникального индекса, а также выполняет операции.

space:update – это псевдоним для операции «обновить по первичному ключу».

tarantool> -- Вставить некоторые тестовые данные -- tarantool> s:insert{3, 4, 5} --- - [3, 4, 5] ... tarantool> s:insert{6, 7, 8} --- - [6, 7, 8] ... tarantool> s:insert{9, 10, 11} --- - [9, 10, 11] ... tarantool> s:insert{12, 13, 14} --- - [12, 13, 14] ... tarantool> -- Здесь ничего не происходит: нет ключа {4} в индексе pk -- s:update({4}, {{'=', 2, 400}}) --- ... tarantool> s:select{} --- - - [3, 4, 5] - [6, 7, 8] - [9, 10, 11] - [12, 13, 14] ... tarantool> -- Обновить по первичному ключу: разрешено -- tarantool> s:update({3}, {{'=', 2, 400}}) --- - [3, 400, 5] ... tarantool> s:select{} --- - - [3, 400, 5] - [6, 7, 8] - [9, 10, 11] - [12, 13, 14] ... tarantool> -- Точно обновить по первичному ключу: разрешено -- tarantool> s.index.pk:update({6}, {{'=', 2, 700}}) --- - [6, 700, 8] ... tarantool> s:select{} --- - - [3, 400, 5] - [6, 700, 8] - [9, 10, 11] - [12, 13, 14] ... tarantool> -- Обновить по уникальному вторичному ключу: разрешено -- tarantool> s.index.sk_uniq:update({10}, {{'=', 2, 1000}}) --- - [9, 1000, 11] ... tarantool> s:select{} --- - - [3, 400, 5] - [6, 700, 8] - [9, 1000, 11] - [12, 13, 14] ... tarantool> -- Обновить по неуникальному вторичному ключу: ошибка -- tarantool> s.index.sk_non_uniq:update({14}, {{'=', 2, 1300}}) --- - error: Get() doesn't support partial keys and non-unique indexes ... tarantool> s:select{} --- - - [3, 400, 5] - [6, 700, 8] - [9, 1000, 11] - [12, 13, 14] ... tarantool> s:truncate() --- ... 

upsert (обновление и вставка) работает с кортежами с четким форматом и выполняет операции обновления.

Если найден старый кортеж по первичному ключу, то операции обновления применяются к старому кортежу, а новый кортеж игнорируется.

Если старый кортеж не найден, то происходит вставка нового кортежа, а операции обновления игнорируются.

Для индексов нет метода upsert – это метод для спейса.

tarantool> s.index.pk.upsert == nil --- - true ... tarantool> s.index.sk_uniq.upsert == nil --- - true ... tarantool> s.upsert ~= nil --- - true ... tarantool> -- В качестве первого аргумента upsert принимает -- tarantool> -- кортеж с четким форматом, НЕ ключ! -- tarantool> s:insert{1, 2, 3} --- - [1, 2, 3] ... tarantool> s:upsert({1}, {{'=', 2, 200}}) --- - error: Tuple field count 1 is less than required by space format or defined indexes (expected at least 3) ... tarantool> s:select{} --- - - [1, 2, 3] ... tarantool> s:delete{1} --- - [1, 2, 3] ... 

upsert превращается в insert, когда старый кортеж не найден по первичному ключу.

tarantool> s:upsert({1, 2, 3}, {{'=', 2, 200}}) --- ... tarantool> -- Как можно увидеть, произошла вставка {1, 2, 3}, -- tarantool> -- а операции обновления не применились. -- s:select{} --- - - [1, 2, 3] ... tarantool> -- Еще одна операция upsert с тем же первичным ключом, -- tarantool> -- но другими значениями прочих полей. -- s:upsert({1, 20, 30}, {{'=', 2, 200}}) --- ... tarantool> -- Старый кортеж был найден по первичному ключу {1}, -- tarantool> -- и применились операции обновления. -- tarantool> -- Новый кортеж игнорируется. -- tarantool> s:select{} --- - - [1, 200, 3] ... 

upsert ищет старый кортеж по первичному индексу, НЕ по вторичному. Это может привести к ошибкам с дубликатами, если новый кортеж нарушает уникальность вторичного индекса.

tarantool> s:upsert({2, 200, 3}, {{'=', 3, 300}}) --- - error: Duplicate key exists in unique index 'sk_uniq' in space 'test' ... s:select{} --- - - [1, 200, 3] ... tarantool> -- Но сработает, если сохраняется уникальность. -- tarantool> s:upsert({2, 0, 0}, {{'=', 3, 300}}) --- ... tarantool> s:select{} --- - - [1, 200, 3] - [2, 0, 0] ... tarantool> s:truncate() --- ... 

replace (замена) работает с кортежами с четким форматом и ищет старый кортеж по первичному ключу нового кортежа.

Если найден старый кортеж, то происходит удаление старого кортежа и вставка нового.

Если старый кортеж не найден, вставляется новый кортеж.

tarantool> s:replace{1, 2, 3} --- - [1, 2, 3] ... tarantool> s:select{} --- - - [1, 2, 3] ... tarantool> s:replace{1, 3, 4} --- - [1, 3, 4] ... tarantool> s:select{} --- - - [1, 3, 4] ... tarantool> s:truncate() --- ... 

Как и upsert, replace может нарушить требования уникальности.

tarantool> s:insert{1, 1, 1} --- - [1, 1, 1] ... tarantool> s:insert{2, 2, 2} --- - [2, 2, 2] ... tarantool> -- Такая замена не сработает, поскольку замена новым кортежем {1, 2, 0} -- tarantool> -- старого кортежа по первичному ключу из индекса 'pk' {1, 1, 1}, -- tarantool> -- приведет к созданию дубликата уникального вторичного ключа в индексе 'sk_uniq': -- tarantool> -- ключ {2} используется и в новом кортеже, и в {2, 2, 2}. -- tarantool> s:replace{1, 2, 0} --- - error: Duplicate key exists in unique index 'sk_uniq' in space 'test' ... tarantool> s:truncate() --- ... 

select (выборка) работает с любыми индексами (первичными/вторичными) и с любыми ключами (уникальными/неуникальными, полными/компонентами).

Если задан компонент ключа, select выполняет поиск всех ключей, префикс которых совпадает с указанным компонентом ключа.

tarantool> s:insert{1, 2, 3} --- - [1, 2, 3] ... tarantool> s:insert{4, 5, 6} --- - [4, 5, 6] ... tarantool> s:insert{7, 8, 9} --- - [7, 8, 9] ... tarantool> s:insert{10, 11, 9} --- - [10, 11, 9] ... tarantool> s:select{1} --- - - [1, 2, 3] ... tarantool> s:select{} --- - - [1, 2, 3] - [4, 5, 6] - [7, 8, 9] - [10, 11, 9] ... tarantool> s.index.pk:select{4} --- - - [4, 5, 6] ... tarantool> s.index.sk_uniq:select{8} --- - - [7, 8, 9] ... tarantool> s.index.sk_non_uniq:select{9} --- - - [7, 8, 9] - [10, 11, 9] ... 
Нашли ответ на свой вопрос?
Обратная связь