Redis+Lua - routing calls by mobile operator DEF code
Case: Fast & Easy search for the mobile operator using the def code.First, obtain data for the table. In this case, I used the DEF 9XX set of the Russian codes from csv file.
Source file structure:
АВС/ DEF;От;До;Емкость;Оператор;Регион 900;0000000;0061999;62000;ООО "Т2 Мобайл";Краснодарский край 900;0062000;0062999;1000;ООО "Т2 Мобайл";Ростовская обл. ...
With regular expressions, I converted this to the form as I needed:
http://redis.io _._ _.-``__ ''-._ _.-`` `. `_. ''-._ .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) |`-._`-...-` __...-.``-._|'` _.-'| | `-._ `._ / _.-' | `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-'
def;end range with def;"name:start range with def" |
900;9000061999;"tele2:9000000000" 900;9000062999;"tele2:9000062000" ...
Second, I imported csv to Redis with help ZADD commands.
cat CSV_FILE.csv | awk -F';' '{print "ZADD", $1, $2, $3 "\n"}' | redis-cli --pipe
Mass insertion of data is very easy with awk.
You can test the output by running it without a pipe to
You can test the output by running it without a pipe to
redis-cli
.
Once done, let's use the ZRANGEBYSCORE command to search:
127.0.0.1:6379> ZRANGEBYSCORE 999 9999999998 +inf LIMIT 0 1 Скартел:9999600000
see more about range indexing: https://redislabs.com/redis-best-practices/indexing-patterns/ip-range-indexing/
the same in Russian https://habr.com/ru/post/485672/
the same in Russian https://habr.com/ru/post/485672/
I created this case for use with Freeswitch PBX. FS has mod_hiredis as a Redis backend, but mod_hiredis does not pass ZADD family commands (I could not, may be you). This is not too bad since I am using Lua dialplan. Below is my simple the test script, using the redis-lua client library:
local num = arg[1]; local def = num:sub(2,4); print("def:" .. def); local cut8 = num:sub(2,11); print("cut8:" .. cut8); local redis = require 'redis' local client = redis.connect('127.0.0.1', 6379) local pass = client:auth('REDIS_PASS') local response = client:ping(); local ret = client:zrangebyscore(def,cut8,'+inf',{ limit = {0,1}}); local function has_value (tab, val) for index, value in ipairs(tab) do if value == val then return true end end return false end local ret_sep = ':'; local ret_opsos = ret[1]; local tbl_opsos = {}; if (ret_opsos ~= nil) then ret_opsos:gsub("([^"..ret_sep.."]*)"..ret_sep, function(c) table.insert(tbl_opsos, c); end) else table.insert(tbl_opsos,"ERROR") end local opsos = {'tele2', 'megafon', 'mts', 'beeline'}; local exists = has_value(opsos,tbl_opsos[1]); if ( exists ) then print(exists); else print("Opsos:" .. tbl_opsos[1]) end
Test:
./redis.lua 8999999998 def:999 cut8:999999998 Opsos: Скартел