Best way to store data - matrix (2D array) or something else

At the moment I use two startup scripts to define two key arrays with the following structure
username → IP address and
username → email address

Now my need expands and I want to create array/table/structure like this:
username → ip addres, email addres, status, last status, something else, something else .

I’ve been reading around and I need some directions:

  1. Is using 2D array the best way of storing/manipulating data in Microtik at the moment? Should/Can I use files or something else?

  2. If using arrays is the case, in order for me to access the status of a specific username is there a way (I couldn’t find it) to create a key array of arrays so that I can use the username as a key and then access the ip address, email, status, etc… with their column numbers? What is the most elegant way, cause using foreach and then searching feels too primitive?

Any other recommendations and best practices will be highly appreciated!

Hi ros44,

Not sure what mileage you’re gonna get out of dictionaries. I’ve been having some issues here.

A workaround is quite simple, assuming you always have all fields.
You can store each type of data in it’s own array, in the same order as the usernames array.

i.e.

global func do={
local usernames ("bob","bill","mike")
local ips (192.168.1.1,192.168.1.2,192.168.1.3)
local emails ("bob@domain.com","bill@domain.com","mike@domain.com")
local otherstuff ("lion","tiger","giraffe")


if ($1="print") do={
foreach index,user in=$usernames do={
local ip [:pick $ips $index]
local email [:pick $emails $index]
local somethingelse [:pick $otherstuff $index]

put ("$user,$ip,$email,$somethingelse")
}
}


if ($1="getEmail") do={
local index [:find $usernames $2]
put [:pick $emails $index]
}

if ($1="getStuff") do={
local index [:find $usernames $2]
put [:pick $otherstuff $index]
}

}

which then you can use as such

[kntouskos@sini2] > $func print
bob,192.168.1.1,bob@domain.com,lion
bill,192.168.1.2,bill@domain.com,tiger
mike,192.168.1.3,mike@domain.com,giraffe
[kntouskos@sini2] > $func getEmail bill
bill@domain.com
[kntouskos@sini2] > $func getStuff mike
giraffe

That said, you’re only temporary storing the data. It will be lost on reboot, so you need a way to load it each time.
Reading/writing to file is limited to 4096 bytes. There are some workarounds though.
If your data is static it’s better to just add them in the script.

I may get elegance and clarity… if it works (referring to the issues you had).

Some of the data won’t be static, but I don’t care if it will be lost between reboots of the router. I will use what you suggest considering the fact that you tested it.

Thank you for your time replying to my question.

I found this forum post and did some tests. The result is the code below that seems pretty neat, tidy and readable, and works as I expected.


:global UserDatabase [:toarray ""];

# The key for the array is the username of the user.
# The structure of every user record is as follows:
# password | email | tel | last IP | something | something else |
:set ($UserDatabase->"username1") {"supersecret";"username1@example.com";"+123456789";"0.0.0.0";0;0};
:set ($UserDatabase->"username2") {"megasecret";"username2@example.com";"+987654321";"0.0.0.0";0;0};

# Printing specific property (column) of the data for specific user:
:put ($UserDatabase->"username1"->0);

Can someone elaborate if this approach has some issues or disadvantages?
What is the name of this data type I’ve created? Is it called key array of arrays?

is great a piece of code.

Any idea how to make

 :put [ :find $UserDatabase "username1"  -1 ]

wo to work?
I get only an empty result.

See http://forum.mikrotik.com/t/multi-dimensional-arrays/96496/1