How to create a space in Tarantool? - lua

I've started Tarantool and have called box.cfg{} for the first configuring.
The next step: I want to create a space in Tarantool.
I read the documentation but I didn't quite understand everything.
How I should do it?

You don't need to create the sequence manually; just pass true and tarantool will create a sequence and even delete it when you drop the space. You can also skip the parts option as it defaults to {1, 'unsigned'}
box.space.users:create_index("pk", { if_not_exists = true, sequence = true })

Create it via Box API:
box.schema.sequence.create('user_seq', { if_not_exists = true })
box.schema.create_space('users', { if_not_exists = true, format={
{ name = 'id', type = 'unsigned'},
{ name = 'name', type = 'string'},
{ name = 'age', type = 'unsigned'}}
})
box.space.users:create_index('pk', { parts = { 'id' }, if_not_exists = true })
With if_not_exists, tarantool won't try to create space if it already exists.
Creating the index is mandatory because Tarantool doesn't allow you to insert data in space without any indexes.
After creating the space, you can insert and select data:
box.space.users:insert({ box.sequence.user_seq:next(), 'Artur Barsegyan', 24 })
box.space.users:get({1})
---
- - [1, 'Artur Barsegyan']
...
You can read more in the documentation.

Related

How to add new field to Tarantool space

I have a following space schema in Tarantool
box.schema.space.create('customer')
format = {
{name = 'id', type = 'string'},
{name = 'last_name', type = 'string'},
}
box.space.customer:format(format)
box.space.customer:create_index('id', {parts = {{field = 'id', is_nullable = false}}})
box.space.customer:replace({'1', 'Ivanov'})
I want to add the new field first_name to this space. What's the way I can do that?
Before answering a question we should discuss a format method.
format - it’s a space option that allows you to get value from a tuple by name. Actually tuple is a “list” of values and any field could be accessed by field number.
What’s next? E.g. you have a simple schema.
box.schema.space.create('customer')
box.space.customer:format(format)
box.space.customer:create_index('id', {parts = {{field = 'id', is_nullable = false}}})
box.space.customer:replace({'1', 'Ivanov'})
Let’s define new format that has the third field - first_name.
new_format = {
{name = 'id', type = 'string'},
{name = 'last_name', type = 'string'},
{name = 'first_name', type = 'string'},
}
box.space.customer:format(new_format) -- error: our tuple have only two fields
tarantool> box.space.customer:format(new_format)
- --
- error: Tuple field 3 required by space format is missing
...
There are two ways to fix it.
Add new field to the end of tuple with default value.
box.space.customer:update({'1'}, {{'=', 3, 'Ivan'}})
box.space.customer:format(new_format) -- OK
Define new field as nullable
new_format = {
{name = 'id', type = 'string'},
{name = 'last_name', type = 'string'},
{name = 'first_name', type = 'string', is_nullable = true},
}
box.space.customer:format(new_format) -- OK: absence of the third value is acceptable
You can choose one described above variant.
I’ve just add some notes:
You can’t add some value through the absence field (e.g. you have first and second values you should add the third before adding the fourth)
tarantool> box.tuple.new({'1', 'Ivanov'}):update({{'=', 4, 'value'}})
- --
- error: Field 4 was not found in the tuple
...
tarantool> box.tuple.new({'1', 'Ivanov'}):update({{'=', 3, box.NULL}, {'=', 4, 'value'}})
- --
- ['1', 'Ivanov', null, 'value']
...
Filling in the field with the default value can be quite a long operation if you have a lot of data. Please be careful when apply any migratons.
Read more about format method in the documentation.

How to make a select via secondary indexes in Tarantool?

I create a space with two indexes — primary and secondary:
box.schema.sequence.create('user_seq', { if_not_exists = true })
box.schema.space.create('user', {
if_not_exists = true,
format = {
{ name = 'id', type = 'unsigned'},
{ name = 'bio', type = 'string'}
}
})
box.space.user:create_index('id', {
sequence = 'user_seq',
parts = {'id'}
})
box.space.user:create_index('bio', {
parts = {'bio'},
if_not_exists = true,
unique = false
})
Insert the tuple:
tarantool> box.space.user:insert({ box.sequence.user_seq:next(), 'other stuff'})
---
- [1, 'other stuff']
...
I've tried to search like this:
box.space.user:select({'other stuff'})
And got the error:
- error: 'Supplied key type of part 0 does not match index part type: expected unsigned'
How I should search via secondary indexes?
The documentation said:
index.index-name is optional. If it is omitted, then the assumed index is the first (primary-key) index. Therefore, for the example above, box.space.tester:select({1}, {iterator = 'GT'}) would have returned the same two rows, via the ‘primary’ index.
Use that secondary index explicitly:
tarantool> box.space.user.index.bio:select({'other stuff'})
---
- - [1, 'other stuff']
...
Read more about it in the documentation.

Lua table.insert - strange behaviour when inserting to table

I'm having a bit of a hard time figuring out why my code is behaving the way it is. I have a table named players, structured as key, value pairs. The values are also nested tables (items). Each item, should contain at least one unique identifier, named 'id', contained withing the nested table (key name) 'specs'.
players = {
['identifier_one'] = {
{
["label"] = "Flashlight",
["weight"] = 1,
["name"] = "WEAPON_FLASHLIGHT",
["specs"] = {
["pockets"] = false,
["id"] = "ZT345", --This is our unique identifier
["equip"] = true,
["stack"] = 1,
["craft"] = true
}
},
{
["label"] = "Flashlight",
["weight"] = 1,
["name"] = "WEAPON_FLASHLIGHT",
["specs"] = {
["pockets"] = false,
["id"] = "ACF124",
["equip"] = true,
["stack"] = 1,
["craft"] = true
}
}
},
['another_item'] = {
...
},
}
I've got the data structure writing correctly. However, when I insert a new nested item, it's adding the newItem to the next increment within the table as expected, and at the same time it's overwriting all of the previus indexes. So the previous items ['spec']['id'] becomes the newItem id if that makes sense? So looking at the above layout, the previous id 'ZT345' would become 'ACF124'. Thus making the two items identical.
When I print out what the newItem consists off, everything is perfect and should write to the table as intended. At first, I thought it may have been something related to the encoding the table into json when writing to the database. However, if I print out the players[identifier] table, after inserting the newItem, it has then overwritten all previous indexes. So I'm pretty certain the issue is upon inserting the newItem to my players[identifier]
My code is as follows:
ESX.RegisterServerCallback('zombie-inventory:itemCheck', function(source, cb, item)
--check our item is allowed to be added.
if items[item] then
local src = source
local identifier = getIdentifier(src)
local newItem = items[item]
if string.match(item, 'WEAPON') then
newItem['specs'][1].id = genId(players[identifier])
end
--This point is where the code falls apart.
table.insert(players[identifier], newItem)
MySQL.Async.execute('UPDATE `user_inventory` SET `inventory` = #inventory WHERE `identifier` = #identifier', {
['#identifier'] = identifier,
['#inventory'] = json.encode(players[identifier])
})
cb(true)
else
print(('[inventory] [^3WARNING^7] invalid item for itemCheck cb: %s'):format(item))
end
end)
Just to add, the genId() function is 100% returning a unique id, I've printed the id numerous times, and it's always different.

ui-grid: How to use function for columnDefs

For some reason I need to create headers dynamically because of component I used.
So I have a function which and that function I want to use to provide values to columnDefs
ctrl.getColumnDefs = () => {
let columns = []
if (name === 'deamon') {
var normalCol = {
field: 'name',
enableSorting: true,
cellTooltip: (row, col) => row.entity[col.field],
enableCellEdit: false
};
return columns.push(normalCol);
}
Then I am using
ctrl.grid = {
columnDefs: getColumnDefs()
}
Which is throwing TypeError: self.options.columnDefs.forEach is not a function
You are returning the value of push. That returns the new length of the array as per docs here.
You probably want to return columns instead of push.
Probably you want this
columns.push(normalCol)
return columns

Lua Tables Assigning values to key in tables

Um what's the difference between in assigning values:
Lesson["Maths"] = {grade = 10, class = 3}
and
Lesson["Maths"] = {["grade"] = 10, ["class"] = 3}
Which one should I go if I want to assign a value to a key in a table? Or which one is more used? Thanks a lot
In your case, both of them are the same. The first usage fails when you want keys with special characters in them:
tEx = {
failed-approach = true,
}
The code segment above will result in an error and you would be forced to follow the second method of creating keys:
tEx = {
['failed-approach'] = false,
}
Both of the approaches are same and it doesn't matter which one you wish to use.

Resources