{"id":404999,"date":"2024-06-29T18:03:15","date_gmt":"2024-06-29T18:03:15","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=404999"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=404999","title":{"rendered":"<span>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Tarantool \u043d\u0430 Golang \u0432\u043c\u0435\u0441\u0442\u043e Lua<\/span>"},"content":{"rendered":"<div><!--[--><img loading=\"lazy\" decoding=\"async\" height=\"1\" src=\"https:\/\/top-fwz1.mail.ru\/counter?id=3200881;js=na\" style=\"display:none;\" width=\"1\"><img loading=\"lazy\" decoding=\"async\" height=\"1\" src=\"https:\/\/www.facebook.com\/tr?id=1220899431627792&amp;ev=PageView&amp;noscript=1\" style=\"display:none;\" width=\"1\"><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/92\/ed\/vv\/92edvvnp--vq2qd9gawm9zdbtiy.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/92\/ed\/vv\/92edvvnp--vq2qd9gawm9zdbtiy.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u042f\u0434\u0440\u043e Tarantool-\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 C, \u0430 \u0432\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0430 Lua. \u042d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u043d\u043e \u0438 \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Tarantool, \u043d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432\u0441\u0435\u0433\u043e \u0442\u0440\u0438 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 \u043a\u043e\u0434\u0430 \u043d\u0430 Lua. \u0410 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 Golang. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0435\u0449\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u044f \u0434\u0430\u044e \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043d\u0430 Python. \u0427\u0442\u043e \u0437\u0430 \u043f\u0440\u043e\u0435\u043a\u0442? \u0414\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043a\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435: \u0434\u043e\u043c, \u0440\u0430\u0431\u043e\u0442\u0430, \u043f\u0435\u0440\u0432\u043e\u0435 \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u0435, \u043f\u0435\u0440\u0432\u044b\u0439 Hello World, \u043f\u0435\u0440\u0432\u044b\u0439 &#171;too long wal write&#187; Tarantool.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u041e\u0431\u0449\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u041d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0432\u043e\u0441\u0445\u0438\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c Leaflet \u0438 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u0440\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0431\u0430\u0437\u043e\u0439 OpenStreetMap.<\/p>\n<p>  <\/p>\n<p>Golang \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0438 \u0430\u043f\u0438\u0448\u043a\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u0440\u0442\u043e\u0439:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043a\u0438;<\/li>\n<li>\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0435\u0442\u043e\u043a \u043f\u0440\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u043a\u0430\u0440\u0442\u0435;<\/li>\n<li>\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u043a.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>Tarantool \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043a\u0438 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e geo-\u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0442\u043a\u0438 \u0437\u0430 4 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b (\u043f\u0440\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u043a\u0430\u0440\u0442\u0435).<\/p>\n<p>  <\/p>\n<h2 id=\"soderzhanie\">\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<ol>\n<li>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 Tarantool \u0438 Lua<\/li>\n<li>\u041a\u0430\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 \u0411\u0414<\/li>\n<li>\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/li>\n<li>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0411\u0414<\/li>\n<li>Golang \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<br \/> \n<ol>\n<li>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0411\u0414<\/li>\n<li>HTTP-\u0441\u0435\u0440\u0432\u0435\u0440<\/li>\n<li>HTTP API<\/li>\n<\/ol>\n<\/li>\n<li>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434<\/li>\n<li>Golang-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0446\u0435\u043b\u0438\u043a\u043e\u043c <\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/li>\n<li>\u0422\u043e\u0442 \u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430 Python<\/li>\n<li>\u0414\u043e\u043a\u0440\u0443\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0432 \u043f\u0440\u043e\u0434<\/li>\n<li>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/li>\n<\/ol>\n<p>  <\/p>\n<h2 id=\"vvedenie-v-tarantool-i-lua\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 Tarantool \u0438 Lua<\/h2>\n<p>  <\/p>\n<p>\u041e\u0441\u0432\u0435\u0436\u0438\u043c \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Tarantool. \u0417\u0434\u0435\u0441\u044c \u044f \u0441\u0434\u0435\u043b\u0430\u044e \u044d\u0442\u043e \u0432 \u0434\u0432\u0430 \u0430\u0431\u0437\u0430\u0446\u0430, \u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435: <a href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/562192\/\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 in-memory \u0421\u0423\u0411\u0414: 10 \u043b\u0435\u0442 \u043e\u043f\u044b\u0442\u0430 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>.<\/p>\n<p>  <\/p>\n<ul>\n<li>Tarantool \u2014 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u0430\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u0430\u044f NoSQL \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/li>\n<li>Tarantool \u0445\u0440\u0430\u043d\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/li>\n<li>Tarantool \u2014 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u043a\u0430\u0436\u0434\u0443\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u043f\u0438\u0448\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432 \u0436\u0443\u0440\u043d\u0430\u043b \u043d\u0430 \u0434\u0438\u0441\u043a.<\/li>\n<li>Tarantool \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0440\u0430\u0437 \u0432 \u0447\u0430\u0441 \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0434\u0438\u0441\u043a.<\/li>\n<li>Tarantool \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 C.<\/li>\n<li>Lua \u0432\u0441\u0442\u0440\u043e\u0435\u043d \u0432 Tarantool.<\/li>\n<li>Lua \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u0443\u044e\u0449\u0438\u043c Just-In-Time \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c.<\/li>\n<li>Lua \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0430\u0437\u0435 \u0437\u0430 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434\u044b.<\/li>\n<li>Lua \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0439 \u044f\u0437\u044b\u043a \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u043e: \u043e\u0442 \u0438\u0433\u0440 \u0434\u043e \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432.<\/li>\n<li>Lua \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041a\u0430\u043a\u0438\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Lua \u0438 LuaJIT \u0432 Tarantool:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041a\u043e\u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043c\u043d\u043e\u0433\u043e\u0437\u0430\u0434\u0430\u0447\u043d\u043e\u0441\u0442\u044c.<br \/> \n<ul>\n<li>\u0412 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430.<\/li>\n<li>\u0417\u0430\u0434\u0430\u0447\u0430 <strong>\u0434\u043e\u043b\u0436\u043d\u0430<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0437\u0432\u0430\u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0438\u043b\u0438 \u044f\u0432\u043d\u043e.<br \/> \n<ul>\n<li>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043d\u0435\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432 async\/await, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0433\u043b\u0430\u0437\u0443 \u0437\u0430\u0446\u0435\u043f\u0438\u0442\u044c\u0441\u044f \u0437\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0444\u0430\u0439\u0431\u0435\u0440\u044b (\u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b).<\/li>\n<li>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 2 \u0413\u0431, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 Tarantool \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e.<\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/493642\/\">\u041e\u0434\u0438\u043d \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c<\/a>.<\/li>\n<li>\u041d\u0435 \u0441\u0430\u043c\u044b\u0439 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 Incremental Mark&amp;Sweep Garbage Collector.<\/li>\n<li>\u0421\u043f\u043e\u0440\u043d\u043e, \u043d\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f (\u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e \u043f\u043b\u044e\u0441).<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041c\u0430\u043b\u043e \u043a\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u043d\u043e\u0439 \u043f\u0443\u043b\u0435\u0439. (\\&lt;\u0448\u0451\u043f\u043e\u0442\u043e\u043c>\u043d\u043e Common Lisp \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043b\u0443\u0447\u0448\u0438\u0439 \u0438\u0437 \u043b\u0443\u0447\u0448\u0438\u0445\\&lt;\\\/\u0448\u0451\u043f\u043e\u0442\u043e\u043c>). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Golang \u0438 Python.<\/p>\n<p>  <\/p>\n<h2 id=\"kak-prilozhenie-vzaimodeystvuet-s-tarantool\">\u041a\u0430\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 Tarantool<\/h2>\n<p>  <\/p>\n<p>\u042f \u0445\u043e\u0447\u0443 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0445\u0435\u043c\u0435 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 Tarantool \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 Golang. \u0417\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, Tarantool \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043d\u0430 \u0434\u0438\u0441\u043a.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/td\/gv\/tt\/tdgvtt-cts_ulfx0bovjizmbjky.gif\" data-src=\"https:\/\/habrastorage.org\/webt\/td\/gv\/tt\/tdgvtt-cts_ulfx0bovjizmbjky.gif\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"nachinaem-stroit-prilozhenie\">\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (3 \u0441\u0442\u0440\u043e\u043a\u0438 Lua).<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Golang \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (150 \u0441\u0442\u0440\u043e\u043a Golang).<br \/> \n<ul>\n<li>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435<\/li>\n<li>\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/li>\n<li>\u0418\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0431\u0430\u0437\u0435<\/li>\n<li>HTTP-\u0441\u0435\u0440\u0432\u0435\u0440<\/li>\n<li>HTTP API<\/li>\n<\/ul>\n<\/li>\n<li>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043d\u0430 HTML\/JS \u0441 Leaflet \u0438 OpenStreetMap (150 \u0441\u0442\u0440\u043e\u043a HTML\/JS).<br \/> \n<ul>\n<li>\u0412\u0438\u0434\u0436\u0435\u0442<\/li>\n<li>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u043a Golang-\u0431\u0435\u043a\u0435\u043d\u0434\u0443<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>  <\/p>\n<h2 id=\"konfiguraciya-bazy-dannyh-vsyo-taki-na-lua\">\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (\u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0430 Lua)<\/h2>\n<p>  <\/p>\n<ul>\n<li>Redis \u0433\u043e\u0432\u043e\u0440\u0438\u0442: \u00ab\u0421\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0439 \u043c\u0435\u043d\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u0444\u0430\u0439\u043b\u0435\u00bb<\/li>\n<li>Mongo \u0433\u043e\u0432\u043e\u0440\u0438\u0442: \u00ab\u0421\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0439 \u043c\u0435\u043d\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e YAML \u0444\u0430\u0439\u043b\u0430\u00bb<\/li>\n<li>Tarantool \u0433\u043e\u0432\u043e\u0440\u0438\u0442: \u00ab\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439 Lua \u0441\u043a\u0440\u0438\u043f\u0442\u00bb<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Tarantool \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443, \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e \u0442\u0440\u0438 Lua-\u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>box.cfg<\/code><\/li>\n<li><code>box.schema.user.create<\/code><\/li>\n<li><code>box.schema.user.grant<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>box.cfg<\/strong><\/p>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u0441\u044c Tarantool. \u0427\u0430\u0441\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435. \u0414\u0440\u0443\u0433\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>  <\/p>\n<p><strong>box.schema.user.create<\/strong><\/p>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>  <\/p>\n<p><strong>box.schema.user.grant<\/strong><\/p>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u0442, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438 \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Tarantool-\u0430 \u2014 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 Lua.<\/p>\n<p>  <\/p>\n<pre><code class=\"lua\">-- \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e iproto box.cfg({listen=\"127.0.0.1:3301\"}) -- \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f box.schema.user.create('storage', {password='passw0rd', if_not_exists=true}) -- \u0414\u0430\u0451\u043c \u0432\u0441\u0435-\u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0430 box.schema.user.grant('storage', 'super', nil, nil, {if_not_exists=true}) -- \u0427\u0443\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0432 iproto, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b require('msgpack').cfg{encode_invalid_as_nil = true}<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c Lua \u0437\u0430\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<h2 id=\"golang-prilozhenie\">Golang-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0412 Golang-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 Tarantool \u0438 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440. \u042d\u0442\u043e \u0434\u0432\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438\u0445 \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438.<\/p>\n<p>  <\/p>\n<h2 id=\"rabota-s-tarantool\">\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 Tarantool<\/h2>\n<p>  <\/p>\n<h3 id=\"podklyuchenie-k-tarantool\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a Tarantool<\/h3>\n<p>  <\/p>\n<p>\u0412 Tarantool \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b iproto. \u041e\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 msgpack. \u0410 msgpack \u2014 \u044d\u0442\u043e \u0430\u043d\u0430\u043b\u043e\u0433 \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e JSON.<\/p>\n<p>  <\/p>\n<p>\u041a Tarantool \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0412 \u0441\u0432\u043e\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0434\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043c \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0433\u043e\u0440\u0443\u0442\u0438\u043d.<\/p>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  import (     \"fmt\"     \"github.com\/tarantool\/go-tarantool\" )  func main() {     opts := tarantool.Opts{User: \"storage\", Pass: \"passw0rd\"}     conn, err := tarantool.Connect(\"127.0.0.1:3301\", opts)     if err != nil {         panic(err)     }     defer conn.Close() }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"shema-dannyh\">\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430 \u043e\u0434\u043d\u043e\u043c \u0443\u0437\u043b\u0435 Tarantool \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u0430\u043d\u043d\u044b\u0435 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u043f\u0435\u0439\u0441\u044b == \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 \u043c\u0438\u0440\u0435 SQL. \u041a \u0434\u0430\u043d\u043d\u044b\u043c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441, \u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0442\u043e\u0440\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443:<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>id<\/th>\n<th>coordinates<\/th>\n<th>comment<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>string<\/td>\n<td>[double, double]<\/td>\n<td>string<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u0412 \u043f\u043e\u043b\u0435 <code>id<\/code> \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u0430\u043c\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c.<br \/>  \u0412 \u043f\u043e\u043b\u0435 <code>coordinates<\/code> \u2014 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043c\u0430\u0440\u043a\u0435\u0440\u0430 (\u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 \u0434\u0432\u0443\u0445 double).<br \/>  \u0412 \u043f\u043e\u043b\u0435 <code>comment<\/code> \u2014 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043f\u0435\u0439\u0441 geo \u0438\u0437 Golang. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u043c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <code>box.schema.space.create<\/code>. \u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u0438\u043c\u044f \u0441\u043f\u0435\u0439\u0441\u0430, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0446\u0438\u0438. \u0412 \u043e\u043f\u0446\u0438\u044f\u0445 \u043c\u044b \u0443\u043a\u0430\u0436\u0435\u043c \u0444\u043b\u0430\u0433 <code>if_not_exist = true<\/code>. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 Golang-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u0440\u0438 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0441\u043f\u0435\u0439\u0441\u0435 \u043d\u0435 \u0431\u0440\u043e\u0441\u0430\u043b\u0430\u0441\u044c \u043e\u0448\u0438\u0431\u043a\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">_, err = conn.Call(\"box.schema.space.create\", []interface{}{         \"geo\",         map[string]bool{\"if_not_exists\": true}})<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u0434\u0430\u0434\u0438\u043c \u0441\u0445\u0435\u043c\u0443 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>box.space.geo:format<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">_, err = conn.Call(\"box.space.geo:format\", [][]map[string]string{         {             {\"name\": \"id\", \"type\": \"string\"},             {\"name\": \"coordinates\", \"type\": \"array\"},             {\"name\": \"comment\", \"type\": \"string\"},         }})<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432 Golang \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type GeoObject struct {     Id          string     `json:\"id\"`     Coordinates [2]float64 `json:\"coordinates\"`     Comment     string     `json:\"comment\"` }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"indeksaciya\">\u0418\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u043f\u0435\u0439\u0441\u043e\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447. \u0418\u043d\u0430\u0447\u0435 \u043b\u044e\u0431\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 \u0441\u043f\u0435\u0439\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>box.space.geo:create_index<\/code>. \u0414\u0432\u043e\u0435\u0442\u043e\u0447\u0438\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430-\u0441\u043f\u0435\u0439\u0441\u0430 <code>box.space.geo<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0438\u043c\u044f;<\/li>\n<li>\u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430;<\/li>\n<li>\u0444\u043b\u0430\u0433 \u0434\u043b\u044f \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">_, err = conn.Call(\"box.space.geo:create_index\", []interface{}{     \"primary\",     map[string]interface{} {         \"parts\":         []string{\"id\"},         \"if_not_exists\": true}})<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"geoindeks\">\u0413\u0435\u043e\u0438\u043d\u0434\u0435\u043a\u0441<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0433\u0435\u043e\u0438\u043d\u0434\u0435\u043a\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0435\u0433\u0438\u043e\u043d\u0435.<\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0438\u043c\u044f;<\/li>\n<li>\u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430;<\/li>\n<li>\u0442\u0438\u043f \u0438\u043d\u0434\u0435\u043a\u0441\u0430 RTREE;<\/li>\n<li>\u0438\u043d\u0434\u0435\u043a\u0441 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b;<\/li>\n<li>\u0444\u043b\u0430\u0433 \u0434\u043b\u044f \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">_, err = conn.Call(\"box.space.geo:create_index\", []interface{}{     \"geoidx\",     map[string]interface{}{         \"parts\":         []string{\"coordinates\"},         \"type\":          \"RTREE\",         \"unique\":        false,         \"if_not_exists\": true}})<\/code><\/pre>\n<p>  <\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e<\/strong><\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f, \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u043e\u0432\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0430\u0441\u044c \u0432 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">conn, err = tarantool.Connect(\"127.0.0.1:3301\", opts) if err != nil {     panic(err) } defer conn.Close()<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"zapis-dannyh\">\u0417\u0430\u043f\u0438\u0441\u044c \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u044f \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 Golang-\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 <code>InsertTyped<\/code>.<\/p>\n<p>  <\/p>\n<p><code>InsertTyped<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443, \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0438\u043c\u044f \u0441\u043f\u0435\u0439\u0441\u0430;<\/li>\n<li>\u0434\u0430\u043d\u043d\u044b\u0435;<\/li>\n<li>\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0442\u0430\u043f\u043b\u043e\u0432.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0434\u0435\u0441\u044c \u044f \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0442\u0430\u043f\u043b <code>{\"Indisko\", {299.073, 148.857}, \"Indian Food\" }<\/code> \u0432 \u0441\u043f\u0435\u0439\u0441 <code>geo<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">var tuples []GeoObject err = conn.InsertTyped(\"geo\", []interface{}{     \"Indisko\",     []float64{299.073, 148.857},     \"Indian Food\",},      &amp;tuples)<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"udalenie-dannyh\">\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f Golang-\u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>DeleteTyped<\/code>.<br \/>  \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0441\u043f\u0435\u0439\u0441;<\/li>\n<li>\u0438\u043d\u0434\u0435\u043a\u0441;<\/li>\n<li>\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f;<\/li>\n<li>\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0442\u0430\u043f\u043b\u043e\u0432.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0434\u0435\u0441\u044c \u044f \u0443\u0434\u0430\u043b\u044f\u044e \u0442\u0430\u043f\u043b, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 <code>\"Indisko\"<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">var tuples []GeoObject err = conn.DeleteTyped(\"geo\", \"primary\", []interface{}{\"Indisko\"}, &amp;tuples)<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"zapros-dannyh\">\u0417\u0430\u043f\u0440\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>  <\/p>\n<p>NoSQL-\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445: <code>select<\/code>. \u041e\u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u0447\u0435\u043c <code>SELECT<\/code> \u0438\u0437 SQL-\u043c\u0438\u0440\u0430. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0441\u043a\u043e\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0434\u0430\u043d\u043d\u044b\u043c, \u044f \u043f\u043e\u043a\u0430\u0436\u0443 \u044d\u0442\u043e \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u044b \u0432\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a geo-\u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c <code>select<\/code> \u0442\u0430\u043c.<\/p>\n<p>  <\/p>\n<h4 id=\"tablichnye-dannye-dlya-primera\">\u0422\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430<\/h4>\n<p>  <\/p>\n<p>\u041d\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0433\u0435\u043e\u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0441 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c \u0438\u0433\u0440 \u0438 \u0441 \u043f\u043e\u043b\u044f\u043c\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440;<\/li>\n<li>\u0438\u043c\u044f \u0438\u0433\u0440\u044b;<\/li>\n<li>\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f \u0438\u0433\u0440\u044b;<\/li>\n<li>\u0446\u0435\u043d\u0430.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u0432\u0442\u043e\u0440\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u043f\u043e \u0434\u0432\u0443\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0430\u043c: \u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f \u0438 \u0426\u0435\u043d\u0430. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 NoSQL-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0438 \u0431\u044b \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<p>\u0417\u0435\u043b\u0451\u043d\u043e\u0439 \u0448\u0442\u0440\u0438\u0445\u043e\u0432\u043a\u043e\u0439 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432.<br \/>  \u0417\u0435\u043b\u0451\u043d\u044b\u043c\u0438 \u0441\u0442\u0440\u0435\u043b\u043a\u0430\u043c\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 \u0438\u043d\u0434\u0435\u043a\u0441\u0435. \u042d\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0441\u043d\u043e\u0439 \u043e\u0431\u0432\u043e\u0434\u043a\u043e\u0439 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<br \/>  \u041a\u0440\u0430\u0441\u043d\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u0440\u0430\u0441\u043d\u043e\u0439 \u043e\u0431\u0432\u043e\u0434\u043a\u0438 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u044b.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/sm\/uv\/al\/smuvaltb1llduwmunyadjaosdxk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/sm\/uv\/al\/smuvaltb1llduwmunyadjaosdxk.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/yp\/qr\/nl\/ypqrnly-qkqakhlklh4h9xjh1qg.png\" data-src=\"https:\/\/habrastorage.org\/webt\/yp\/qr\/nl\/ypqrnly-qkqakhlklh4h9xjh1qg.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/rt\/su\/le\/rtsulecf4igfes8kmtn8ypzckxq.png\" data-src=\"https:\/\/habrastorage.org\/webt\/rt\/su\/le\/rtsulecf4igfes8kmtn8ypzckxq.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/dn\/mk\/pi\/dnmkpikvtn2ymgew8uk5kh8o22o.png\" data-src=\"https:\/\/habrastorage.org\/webt\/dn\/mk\/pi\/dnmkpikvtn2ymgew8uk5kh8o22o.png\"\/><\/p>\n<p>  <\/p>\n<h4 id=\"geodannye\">\u0413\u0435\u043e\u0434\u0430\u043d\u043d\u044b\u0435<\/h4>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u043c\u043e\u0434\u0435\u043b\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0433\u0435\u043e\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 <code>select<\/code> \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u0430\u043a.<\/p>\n<p>  <\/p>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0434\u0432\u0443\u043c\u0435\u0440\u043d\u0430\u044f. \u0422\u043e\u0447\u043a\u0438 \u2014 \u044d\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 x,y. \u041f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u2014 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u043b\u0435\u0432\u043e\u0433\u043e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0438 \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0433\u043b\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u0440\u0441\u043d\u044b\u043c \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d \u0438\u0441\u043a\u043e\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442: \u0442\u043e\u0447\u043a\u0430 \u0438\u043b\u0438 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a. \u0417\u0435\u043b\u0435\u043d\u044b\u043c \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0442\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/aq\/ef\/4y\/aqef4yh_rdj-kdr1xo-do0gmdxa.png\" data-src=\"https:\/\/habrastorage.org\/webt\/aq\/ef\/4y\/aqef4yh_rdj-kdr1xo-do0gmdxa.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/9y\/om\/w6\/9yomw6_anzi1rxu6mo9ewdsrqes.png\" data-src=\"https:\/\/habrastorage.org\/webt\/9y\/om\/w6\/9yomw6_anzi1rxu6mo9ewdsrqes.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/l9\/m3\/z8\/l9m3z8h5wbsvf1fog_s3ag575pi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/l9\/m3\/z8\/l9m3z8h5wbsvf1fog_s3ag575pi.png\"\/><\/p>\n<p>  <\/p>\n<h3 id=\"signatura-select\">\u0421\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 select<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>SelectTyped<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>c\u043f\u0435\u0439\u0441;<\/li>\n<li>\u0438\u043d\u0434\u0435\u043a\u0441;<\/li>\n<li>\u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435, \u043b\u0443\u0447\u0448\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c 0;<\/li>\n<li>\u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432;<\/li>\n<li>\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443;<\/li>\n<li>\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430. \u0414\u043b\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0445 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0439, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0441\u0430\u043c\u043e\u0439 \u0441\u0442\u0430\u0440\u0448\u0435\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438;<\/li>\n<li>\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e \u043f\u043e\u0438\u0441\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043f\u0435\u0439\u0441\u0435 geo \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443 <code>geoidx<\/code>. \u0418 \u0438\u0449\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 <code>(tarantool.IterLe)<\/code> \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0433\u0438\u043e\u043d \u043f\u043e\u0438\u0441\u043a\u0430 <code>{0, 0, 300, 400}<\/code>. Tarantool \u0432\u0435\u0440\u043d\u0435\u0442 \u043c\u043d\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043b\u0435\u0436\u0430\u0442 \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0435 \u043e\u0442 \u0432\u0435\u0440\u0448\u0438\u043d\u044b 0,0 \u0434\u043e \u0432\u0435\u0440\u0448\u0438\u043d\u044b 300,400.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">var tuples []GeoObject err = conn.SelectTyped(\"geo\", \"geoidx\", 0, 10, tarantool.IterLe,      []interface{}{0, 0, 300, 400},      &amp;tuples)<\/code><\/pre>\n<p>  <\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e<\/strong><\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u0440\u043e\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0437\u0430 \u0440\u0430\u0437 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0434\u043e 1000. \u0421\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c 0, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443.<\/p>\n<p>  <\/p>\n<h2 id=\"http-server\">HTTP-\u0441\u0435\u0440\u0432\u0435\u0440<\/h2>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435. \u0412\u043e\u0437\u043c\u0451\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 web-\u0441\u0435\u0440\u0432\u0435\u0440 Golang. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043c, \u043d\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u0442\u0440\u0430\u0448\u043d\u043e. \u042d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 \u0435\u0449\u0435 \u043d\u0430\u0439\u0434\u0443\u0442 \u0441\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u0430\u043c \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432. <\/p>\n<p>  <\/p>\n<pre><code class=\"go\">err = http.ListenAndServe(\"127.0.0.1:8080\", nil) if err != nil {     panic(err) }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"http-api\">HTTP API<\/h3>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u0434\u0430\u0451\u043c <code>index.html<\/code>. \u0421\u0430\u043c <code>index.html<\/code> \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">http.HandleFunc(\"\/\", func(w http.ResponseWriter, r *http.Request) {     http.ServeFile(w, r, \"index.html\") })<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0440\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>\/new<\/code> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432;<\/li>\n<li><code>\/remove<\/code> \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f;<\/li>\n<li><code>\/list<\/code> \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0432 \u0440\u0435\u0433\u0438\u043e\u043d.<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"new\">\/new<\/h3>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c JSON, \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0439 \u043a \u043d\u0430\u043c \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430. \u0417\u0430\u0442\u0435\u043c \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 Tarantool.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">http.HandleFunc(\"\/new\", func(w http.ResponseWriter, r *http.Request) {     dec := json.NewDecoder(r.Body)     obj := &amp;GeoObject{}     err := dec.Decode(obj)     if err != nil {         http.Error(w, err.Error(), http.StatusInternalServerError)         return     }     obj.Id = sid.IdHex()     var tuples []GeoObject     err = conn.InsertTyped(\"geo\", []interface{}{obj.Id, obj.Coordinates, obj.Comment}, &amp;tuples)     if err != nil {         http.Error(w, err.Error(), http.StatusInternalServerError)         return     }     enc := json.NewEncoder(w)     enc.Encode(tuples) })<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"remove\">\/remove<\/h3>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c JSON, \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0439 \u043a \u043d\u0430\u043c \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430. \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 Tarantool \u043f\u043e \u043f\u043e\u043b\u044e \u0441 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u0435\u043c.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">http.HandleFunc(\"\/remove\", func(w http.ResponseWriter, r *http.Request) {     dec := json.NewDecoder(r.Body)     obj := &amp;GeoObject{}     err := dec.Decode(obj)     if err != nil {         http.Error(w, err.Error(), http.StatusInternalServerError)         return     }     var tuples []GeoObject     err = conn.DeleteTyped(\"geo\", \"primary\", []interface{}{obj.Id}, &amp;tuples)     if err != nil {         http.Error(w, err.Error(), http.StatusInternalServerError)         return     }     enc := json.NewEncoder(w)     enc.Encode(tuples) })<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"list\">\/list<\/h3>\n<p>  <\/p>\n<p>\u0412 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0435 <code>\/list<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c get-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u2014 <code>rect<\/code>. \u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 JSON-\u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u043a\u0430\u0440\u0442\u044b: \u043b\u0435\u0432\u043e\u0433\u043e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0443\u0433\u043b\u0430 \u0438 \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 Tarantool \u0441 \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u0442\u0435\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 \u0432 rect-\u0440\u0435\u0433\u0438\u043e\u043d. \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 1000.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">http.HandleFunc(\"\/list\", func(w http.ResponseWriter, r *http.Request) {     rect, ok := r.URL.Query()[\"rect\"]     if !ok || len(rect) &lt; 1 {         http.Error(w, err.Error(), http.StatusInternalServerError)         return     }      var arr []float64     err := json.Unmarshal([]byte(rect[0]), &amp;arr)     if err != nil {         panic(err)     }      var tuples []GeoObject     err = conn.SelectTyped(\"geo\", \"geoidx\", 0, 1000, tarantool.IterLe,         arr,         &amp;tuples)     if err != nil {         http.Error(w, err.Error(), http.StatusInternalServerError)         return     }     enc := json.NewEncoder(w)     enc.Encode(tuples) })<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043c\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Tarantool, \u0442\u0430\u043a \u0438 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. Golang \u0442\u043e\u0436\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0441\u044f, \u0434\u0430\u043b\u044c\u0448\u0435 JS.<\/p>\n<p>  <\/p>\n<h2 id=\"frontend\">\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Leaflet \u043e\u0442 \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440\u0430 \u0410\u0433\u0430\u0444\u043e\u043d\u0446\u0435\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043a\u0430\u0440\u0442\u0435 \u0441 \u043c\u0430\u0440\u043a\u0435\u0440\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0441\u0442\u0438\u043b\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.css\" crossorigin=\"\" \/> &lt;script src=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.js\" crossorigin=\"\">&lt;\/script> &lt;script src=\"https:\/\/unpkg.com\/leaflet-providers@1.0.13\/leaflet-providers.js\" crossorigin=\"\">&lt;\/script><\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043a\u0430\u0440\u0442\u043e\u0439<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">var mymap = L.map('mapid',     { 'tap': false })     .setView([59.95184617254149, 30.30683755874634], 13)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0442\u0443\u0434\u0430 \u0431\u0430\u0437\u0443 OpenStreetMap.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">var osm = L.tileLayer('https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', {     maxZoom: 19,     attribution: '&amp;copy &lt;a href=\"https:\/\/www.openstreetmap.org\/copyright\">OpenStreetMap&lt;\/a> contributors', }).addTo(mymap)<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b, \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">var alreadyloaded = {} var popups = {} function addObject(data) {     if (!(data.id in alreadyloaded)) {         var l = mymap.unproject(L.point(data['coordinates'][0], data['coordinates'][1]), 1)          var description = data['comment']         description += `&lt;br \/>&lt;a href=\"#\" onclick=\"removeObject('${data.id}')\">Remove&lt;\/a>`         popups[data.id] = L.marker(l).addTo(mymap).bindPopup(description)         alreadyloaded[data.id] = data     } } function parse(array) {     array.forEach(addObject) } function errorResponse(error) {     alert('Error: ' + error) } function handleListResponse(res) {     res.json().then(parse).catch(errorResponse) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435. \u0412 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/new<\/code>. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function onMapClick(e) {     var response = window.prompt('\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c?')     if (response != null) {         var p = mymap.project(e.latlng, 1)          var data = {             \"coordinates\": [p.x, p.y],             \"comment\": response,         }          fetch(\"\/new\", {             method: \"POST\",             body: JSON.stringify(data)         })         .then(handleListResponse)         .catch(errorResponse)     } } mymap.on('click', onMapClick)<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u043a\u0430\u0440\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0443, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0441\u043f\u0430\u043c\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function getObjects() {     var bounds = mymap.getBounds()     var northeast = bounds.getNorthEast()     var southwest = bounds.getSouthWest()     var ne = mymap.project(northeast, 1)     var sw = mymap.project(southwest, 1)     var options = {         \"rect\": JSON.stringify([ne.x, ne.y, sw.x, sw.y]),     }      fetch(\"\/list?\" + new URLSearchParams(options))         .then(handleListResponse)         .catch(errorResponse) } var timerId = null function onMapMove(e) {     if (timerId == null) {         timerId = setTimeout(function () {             getObjects()             timerId = null         }, 1000)     } }  mymap.on('move', onMapMove)  timerId = setTimeout(function () {     getObjects()     timerId = null }, 1000)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043f\u043e \u043a\u043b\u0438\u043a\u0443 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0435 \u043d\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u0435.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function removeObject(id) {     if (!(id in alreadyloaded)) {         alert(`Sorry point with ${id} not found`)         return     }     var data = alreadyloaded[id]      popups[id].remove()     delete alreadyloaded[id]     delete popups[id]      fetch(\"\/remove\", {         method: \"POST\",         body: JSON.stringify(data)     })     .catch(errorResponse) }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"prilozhenie-celikom\">\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0446\u0435\u043b\u0438\u043a\u043e\u043c<\/h2>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">init.lua<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">-- \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e iproto box.cfg({listen=\"127.0.0.1:3301\"}) -- \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f box.schema.user.create('storage', {password='passw0rd', if_not_exists=true}) -- \u0414\u0430\u0451\u043c \u0432\u0441\u0435-\u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0430 box.schema.user.grant('storage', 'super', nil, nil, {if_not_exists=true}) -- \u0427\u0443\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0432 iproto, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b require('msgpack').cfg{encode_invalid_as_nil = true}<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">index.html<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"html\">&lt;html>  &lt;head>     &lt;title>The Map&lt;\/title>     &lt;link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.css\" crossorigin=\"\" \/>     &lt;script src=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.js\" crossorigin=\"\">&lt;\/script>     &lt;script src=\"https:\/\/unpkg.com\/leaflet-providers@1.0.13\/leaflet-providers.js\" crossorigin=\"\">&lt;\/script> &lt;\/head>  &lt;body>     &lt;!-- div \u0434\u043b\u044f \u043a\u0430\u0440\u0442\u044b -->     &lt;div id=\"mapid\" style=\"height:100%\">&lt;\/div>     &lt;script>         \/\/ \u041a\u0430\u0440\u0442\u0430         var mymap = L.map('mapid',             { 'tap': false })             .setView([59.95184617254149, 30.30683755874634], 13)          \/\/ \u0421\u043b\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0441 \u0434\u043e\u043c\u0430\u043c\u0438, \u0443\u043b\u0438\u0446\u0430\u043c\u0438 \u0438 \u0442.\u043f.         var osm = L.tileLayer('https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', {             maxZoom: 19,             attribution: '&amp;copy &lt;a href=\"https:\/\/www.openstreetmap.org\/copyright\">OpenStreetMap&lt;\/a> contributors',         }).addTo(mymap)          \/\/ \u0417\u0434\u0435\u0441\u044c \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0442\u0435 \u043c\u0430\u0440\u043a\u0435\u0440\u044b, \u0447\u0442\u043e \u0443\u0436\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435         var alreadyloaded = {}         var popups = {}         \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435         function addObject(data) {             if (!(data.id in alreadyloaded)) {                 \/*                 * \u041a\u0430\u0440\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043d\u0430 \u0448\u0430\u0440\u0435                 * Tarantool \u0445\u0440\u0430\u043d\u0438\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043d\u0430 \u043f\u043b\u043e\u0441\u043a\u043e\u0441\u0442\u0438                 * \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u0434\u0440\u0443\u0433\u0443\u044e                 *\/                 var l = mymap.unproject(L.point(data['coordinates'][0], data['coordinates'][1]), 1)                  var description = data['comment']                 \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430                 description += `&lt;br \/>&lt;a href=\"#\" onclick=\"removeObject('${data.id}')\">Remove&lt;\/a>`                 \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0430\u0440\u043a\u0435\u0440                 popups[data.id] = L.marker(l).addTo(mymap).bindPopup(description)                 alreadyloaded[data.id] = data             }         }         \/\/ \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c json \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0439 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430         function parse(array) {             array.forEach(addObject)         }         function errorResponse(error) {             alert('Error: ' + error)         }         function handleListResponse(res) {             res.json().then(parse).catch(errorResponse)         }          \/\/ \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443         function onMapClick(e) {             var response = window.prompt('\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c?')             if (response != null) {                 \/*                 * \u041a\u0430\u0440\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043d\u0430 \u0448\u0430\u0440\u0435                 * Tarantool \u0445\u0440\u0430\u043d\u0438\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043d\u0430 \u043f\u043b\u043e\u0441\u043a\u043e\u0441\u0442\u0438                 * \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u0434\u0440\u0443\u0433\u0443\u044e                 *\/                 var p = mymap.project(e.latlng, 1)                  var data = {                     \"coordinates\": [p.x, p.y],                     \"comment\": response,                 }                  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430                 fetch(\"\/new\", {                     method: \"POST\",                     body: JSON.stringify(data)                 })                 .then(handleListResponse)                 .catch(errorResponse)             }         }         mymap.on('click', onMapClick)          function getObjects() {              var bounds = mymap.getBounds()             var northeast = bounds.getNorthEast()             var southwest = bounds.getSouthWest()             var ne = mymap.project(northeast, 1)             var sw = mymap.project(southwest, 1)             var options = {                 \"rect\": JSON.stringify([ne.x, ne.y, sw.x, sw.y]),             }              \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432             fetch(\"\/list?\" + new URLSearchParams(options))                 .then(handleListResponse)                 .catch(errorResponse)         }          \/\/ \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u0440\u043a\u0435\u0440\u0430          function removeObject(id) {             if (!(id in alreadyloaded)) {                 alert(`Sorry point with ${id} not found`)                 return             }             var data = alreadyloaded[id]              popups[id].remove()             delete alreadyloaded[id]             delete popups[id]              fetch(\"\/remove\", {                 method: \"POST\",                 body: JSON.stringify(data)             })             .catch(errorResponse)         }          \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u043f\u0440\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u043a\u0430\u0440\u0442\u0435         var timerId = null         function onMapMove(e) {             if (timerId == null) {                 timerId = setTimeout(function () {                     getObjects()                     timerId = null                 }, 1000)             }         }         mymap.on('move', onMapMove)          timerId = setTimeout(function () {             getObjects()             timerId = null         }, 1000)     &lt;\/script> &lt;\/body>  &lt;\/html><\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">map.go<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">package main  import (     \"encoding\/json\"     \"net\/http\"      \"github.com\/chilts\/sid\"     \"github.com\/tarantool\/go-tarantool\" )  \/\/ \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u0435\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\/\u0438\u0437 Tarantool type GeoObject struct {     Id          string     `json:\"id\"`     Coordinates [2]float64 `json:\"coordinates\"`     Comment     string     `json:\"comment\"` }  func main() {     opts := tarantool.Opts{User: \"storage\", Pass: \"passw0rd\"}     conn, err := tarantool.Connect(\"127.0.0.1:3301\", opts)     if err != nil {         panic(err)     }     defer conn.Close()      \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443     _, err = conn.Call(\"box.schema.space.create\", []interface{}{         \"geo\",         map[string]bool{\"if_not_exists\": true}})     if err != nil {         panic(err)     }     \/\/ \u0417\u0430\u0434\u0430\u0434\u0438\u043c \u0442\u0438\u043f\u044b \u043f\u043e\u043b\u0435\u0439     _, err = conn.Call(\"box.space.geo:format\", [][]map[string]string{         {             {\"name\": \"id\", \"type\": \"string\"},             {\"name\": \"coordinates\", \"type\": \"array\"},             {\"name\": \"comment\", \"type\": \"string\"},         }})     if err != nil {         panic(err)     }      \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441     _, err = conn.Call(\"box.space.geo:create_index\", []interface{}{         \"primary\",         map[string]interface{}{             \"parts\":         []string{\"id\"},             \"if_not_exists\": true}})     if err != nil {         panic(err)     }      \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0442\u043e\u0440\u0438\u0447\u043d\u044b\u0439 geo-\u0438\u043d\u0434\u0435\u043a\u0441 \u043f\u043e \u043f\u043e\u043b\u044e \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438     _, err = conn.Call(\"box.space.geo:create_index\", []interface{}{         \"geoidx\",         map[string]interface{}{             \"parts\":         []string{\"coordinates\"},             \"type\":          \"RTREE\",             \"unique\":        false,             \"if_not_exists\": true}})     if err != nil {         panic(err)     }      \/\/ \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445     conn, err = tarantool.Connect(\"127.0.0.1:3301\", opts)     if err != nil {         panic(err)     }     defer conn.Close()      \/\/ \u0412 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0435 \u043e\u0442\u0434\u0430\u0451\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434     http.HandleFunc(\"\/\", func(w http.ResponseWriter, r *http.Request) {         http.ServeFile(w, r, \"index.html\")     })      \/\/ \u041e\u0442\u0434\u0430\u0451\u043c \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0432 url \u0440\u0435\u0433\u0438\u043e\u043d\u0430     http.HandleFunc(\"\/list\", func(w http.ResponseWriter, r *http.Request) {         rect, ok := r.URL.Query()[\"rect\"]         if !ok || len(rect) &lt; 1 {             http.Error(w, err.Error(), http.StatusInternalServerError)             return         }          var arr []float64         err := json.Unmarshal([]byte(rect[0]), &amp;arr)         if err != nil {             panic(err)         }          \/\/ \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 1000 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0440\u0435\u0433\u0438\u043e\u043d\u0435 rect         var tuples []GeoObject         err = conn.SelectTyped(\"geo\", \"geoidx\", 0, 1000, tarantool.IterLe,             arr,             &amp;tuples)         if err != nil {             http.Error(w, err.Error(), http.StatusInternalServerError)             return         }         enc := json.NewEncoder(w)         enc.Encode(tuples)     })      \/\/ \u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430     http.HandleFunc(\"\/new\", func(w http.ResponseWriter, r *http.Request) {         dec := json.NewDecoder(r.Body)         obj := &amp;GeoObject{}         err := dec.Decode(obj)         if err != nil {             http.Error(w, err.Error(), http.StatusInternalServerError)             return         }         \/\/ \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043c\u0430\u0440\u043a\u0435\u0440\u0430         obj.Id = sid.IdHex()         var tuples []GeoObject         \/\/ \u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u0430\u0440\u043a\u0435\u0440         err = conn.InsertTyped(\"geo\", []interface{}{obj.Id, obj.Coordinates, obj.Comment}, &amp;tuples)         if err != nil {             http.Error(w, err.Error(), http.StatusInternalServerError)             return         }         enc := json.NewEncoder(w)         enc.Encode(tuples)     })      \/\/ \u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430     http.HandleFunc(\"\/remove\", func(w http.ResponseWriter, r *http.Request) {         dec := json.NewDecoder(r.Body)         obj := &amp;GeoObject{}         err := dec.Decode(obj)         if err != nil {             http.Error(w, err.Error(), http.StatusInternalServerError)             return         }         \/\/ \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0440\u043a\u0435\u0440 \u043f\u043e \u0435\u0433\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443         var tuples []GeoObject         err = conn.DeleteTyped(\"geo\", \"primary\", []interface{}{obj.Id}, &amp;tuples)         if err != nil {             http.Error(w, err.Error(), http.StatusInternalServerError)             return         }         enc := json.NewEncoder(w)         enc.Encode(tuples)     })      \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c http \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0430\u0434\u0440\u0435\u0441\u0435     err = http.ListenAndServe(\"127.0.0.1:8080\", nil)     if err != nil {         panic(err)     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h2 id=\"zapusk-prilozheniya\">\u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>  <\/p>\n<h3 id=\"zapusk-bazy\">\u0417\u0430\u043f\u0443\u0441\u043a \u0431\u0430\u0437\u044b<\/h3>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0443\u043a\u0430\u043c\u0438 \u0443\u043a\u0430\u0437\u0430\u0432 \u0441\u043a\u0440\u0438\u043f\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">tarantool init.lua<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u044b <code>*.snap<\/code>, <code>*.xlog<\/code>. \u042d\u0442\u043e \u0444\u0430\u0439\u043b\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  <\/p>\n<ul>\n<li><code>*.snap<\/code> \u2014 \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445<\/li>\n<li><code>*.xlog<\/code> \u2014 \u0436\u0443\u0440\u043d\u0430\u043b \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0445 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"zapusk-golang\">\u0417\u0430\u043f\u0443\u0441\u043a Golang<\/h3>\n<p>  <\/p>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c golang \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">go mod init map<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440 \u0438\u0437 Golang \u0432 Tarantool.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">go get github.com\/tarantool\/go-tarantool<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">go get github.com\/chilts\/sid<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0431\u044d\u043a\u0435\u043d\u0434.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">go run .\/map.go<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>http:\/\/127.0.0.1:8080<\/code>, \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u043d\u0435\u0442 \u043a\u0430\u0440\u0442\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0441\u0442\u0430\u0432\u0438\u0442 \u043c\u0430\u0440\u043a\u0435\u0440\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b \u0431\u044b \u043f\u0443\u0442\u044c \u0424\u0440\u043e\u0434\u043e \u0438\u0437 \u0412\u043b\u0430\u0441\u0442\u0435\u043b\u0438\u043d\u0430 \u041a\u043e\u043b\u0435\u0446, \u0435\u0441\u043b\u0438 \u0431\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u0438 \u0432 \u041b\u0435\u043d\u0438\u043d\u0433\u0440\u0430\u0434\u0441\u043a\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/az\/-q\/rp\/az-qrpgmp6rcy52mixja1b93lu4.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/az\/-q\/rp\/az-qrpgmp6rcy52mixja1b93lu4.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"python-prilozhenie\">Python \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0430\u043a\u043e\u0435 \u0436\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Python3. \u041e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0442\u0435\u0445 \u0436\u0435 \u0447\u0430\u0441\u0442\u0435\u0439, \u0447\u0442\u043e \u0438 Golang-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0430\u043f\u043e\u043c\u043d\u044e:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435;<\/li>\n<li>\u0441\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li>\u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435;<\/li>\n<li>\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0431\u0430\u0437\u0435;<\/li>\n<li>HTTP-\u0441\u0435\u0440\u0432\u0435\u0440;<\/li>\n<li>HTTP API.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440 <code>asynctnt<\/code>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0432\u0435\u0431\u0441\u0435\u0440\u0432\u0435\u0440\u0430: aiohttp.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">map.py<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\">import asyncio import json import uuid  import asynctnt from aiohttp import web  conn = None  # \u041e\u0442\u0434\u0430\u0451\u043c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 async def index(request):     return web.FileResponse('.\/index.html', headers={\"Content-type\": \"text\/html; charset=utf-8\"})  # \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u0433\u0435\u043e\u0442\u043e\u0447\u043a\u0438 async def new(request):     data = await request.json()     # \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440     data['id'] = str(uuid.uuid4())     # \u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432 Tarantool     await conn.insert(\"geo\", [data['id'], data['coordinates'], data['comment']])     return web.json_response([data])  # \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0433\u0435\u043e\u0442\u043e\u0447\u043a\u0438 async def remove(request):     data = await request.json()     await conn.delete(\"geo\", [data['id']])     return web.json_response([data])  # \u0412\u043e\u0437\u0432\u0440\u0430\u0442 \u0432\u0441\u0435\u0445 \u0433\u0435\u043e\u0442\u043e\u0447\u0435\u043a \u0432 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u043c \u0440\u0435\u0433\u0438\u043e\u043d\u0435 async def lst(request):     rect = request.rel_url.query['rect']     rect = json.loads(rect)     # \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c 1000 \u0442\u043e\u0447\u0435\u043a \u0438\u0437 \u0431\u0430\u0437\u044b     res = await conn.select('geo', rect, index=\"geoidx\", iterator=\"LE\", limit=1000)     result = []     for tuple in res.body:         result.append({             \"id\": tuple['id'],             \"coordinates\": tuple['coordinates'],             \"comment\": tuple['comment'],         })     return web.json_response(result)  async def main():     global conn     # \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u0432 \u0431\u0430\u0437\u0435     conn = asynctnt.Connection(host='127.0.0.1', port=3301, username=\"storage\", password=\"passw0rd\")     await conn.connect()      # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0434\u043b\u044f \u0433\u0435\u043e\u0442\u043e\u0447\u0435\u043a     await conn.call(\"box.schema.space.create\", [\"geo\", {\"if_not_exists\": True}])     await conn.call(\"box.space.geo:format\", [[         {\"name\": \"id\", \"type\": \"string\"},         {\"name\": \"coordinates\", \"type\": \"array\"},         {\"name\": \"comment\", \"type\": \"string\"},     ]])      # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0443     await conn.call(\"box.space.geo:create_index\", [\"primary\", {\"parts\":[\"id\"], \"if_not_exists\": True}])     # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0433\u0435\u043e\u0438\u043d\u0434\u0435\u043a\u0441     await conn.call(\"box.space.geo:create_index\", [\"geoidx\", {\"parts\":[\"coordinates\"], \"type\":\"RTREE\", \"unique\":False,          \"if_not_exists\": True}])      app = web.Application()     app.add_routes([web.get('\/', index),                 web.get('\/list', lst),                 web.post('\/new', new),                 web.post('\/remove', remove)])      await asyncio.gather(web._run_app(app))  asyncio.run(main())<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"zapusk-python-prilozheniya\">\u0417\u0430\u043f\u0443\u0441\u043a Python \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440 asynctnt.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">pip3 install asynctnt<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c aiohttp.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">pip3 install aiohttp<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0433\u0430\u0441\u0438\u043c Golang-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c python.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">python3 .\/map.py<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u043e\u0442 \u0436\u0435 \u0430\u0434\u0440\u0435\u0441 <a href=\"http:\/\/127.0.0.1:8080\">http:\/\/127.0.0.1:8080<\/a>, \u0442\u0430 \u0436\u0435 \u043a\u0430\u0440\u0442\u0430, \u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 Python \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c. \u0412\u044b\u0431\u0438\u0440\u0430\u0439\u0442\u0435, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u0430\u0441 \u0443\u0434\u043e\u0431\u043d\u0435\u0435.<\/p>\n<p>  <\/p>\n<h2 id=\"v-zaklyuchenie\">\u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/7q\/ie\/c-\/7qiec-huyjqm8ingo8j7mqyo8jq.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/7q\/ie\/c-\/7qiec-huyjqm8ingo8j7mqyo8jq.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0432 Tarantool \u043b\u044e\u0431\u0438\u043c Lua \u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u0430 \u043d\u0435\u043c \u043f\u0438\u0448\u0435\u043c. \u041d\u043e \u043d\u0435 \u0432\u0441\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442 \u043d\u0430\u0448 \u044d\u043d\u0442\u0443\u0437\u0438\u0430\u0437\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0436\u0438\u0442\u044c \u0441 Tarantool \u0431\u0435\u0437 Lua.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043c\u043e\u0451\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043d\u043e \u0442\u0430\u043a\u0438\u043c \u0436\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442, \u043f\u043e\u0433\u043e\u0434\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043a\u0443\u0440\u044c\u0435\u0440\u044b \u0438 \u0442.\u043f.<\/p>\n<p>  <\/p>\n<h3 id=\"chto-predstoyalo-by-sdelat-esli-zapuskat-prilozhenie-v-prod\">\u0427\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u043b\u043e \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043f\u0440\u043e\u0434<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0430\u0432\u0442\u043e\u043c\u043e\u0431\u0438\u043b\u0438, \u043f\u043e\u0433\u043e\u0434\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c websocket-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.<\/li>\n<li>\u0428\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 Cartridge, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u043f\u043e\u043c\u0435\u0449\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/li>\n<li>\u041f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043f\u0440\u0438 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0438 \u043f\u043e \u043a\u0430\u0440\u0442\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f.<br \/> \n<ul>\n<li>\u041b\u0443\u0447\u0448\u0435 \u0434\u043e\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u0435\u0441\u044f \u0440\u0435\u0433\u0438\u043e\u043d\u044b, \u0430 \u043d\u0435 \u0432\u0435\u0441\u044c \u043e\u0431\u0449\u0438\u0439 \u0440\u0435\u0433\u0438\u043e\u043d.<\/li>\n<\/ul>\n<\/li>\n<li>\u041d\u0430 \u0432\u0441\u0435\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445 \u0437\u0443\u043c\u0430 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f <strong>\u0432\u0441\u0435<\/strong> \u043e\u0431\u044a\u0435\u043a\u0442\u044b. \u042d\u0442\u043e \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u0430\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f.<br \/> \n<ul>\n<li>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438, \u043d\u0443\u0436\u043d\u043e \u0430\u0433\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u0443\u043c\u043e\u0432. \u0418 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0443\u043c\u0430.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>UPD<\/strong><\/p>\n<p>  <\/p>\n<h2 id=\"analogichnyy-kod-na-lua\">\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 Lua<\/h2>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Lua \u0432\u043d\u0443\u0442\u0440\u0438 Tarantool<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">init.lua<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">-- \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e iproto box.cfg({listen=\"127.0.0.1:3301\"}) -- \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f box.schema.user.create('storage', {password='passw0rd', if_not_exists=true}) -- \u0414\u0430\u0451\u043c \u0432\u0441\u0435-\u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0430 box.schema.user.grant('storage', 'super', nil, nil, {if_not_exists=true}) -- \u0427\u0443\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0432 iproto, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b require('msgpack').cfg{encode_invalid_as_nil = true}  require('app')<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">app.lua<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local log = require('log') local fio = require('fio') local uuid = require('uuid') local json = require('json')  --[[     \u041e\u0442\u0434\u0430\u0451\u043c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0447\u0430\u0441\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 ]] local function index(request)     return { body=fio.open('index.html'):read() } end  --[[     \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u043e\u0442\u0437\u044b\u0432 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 ]] local function newplace(request)     local place = {}     -- json \u043e\u0442 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430     local obj = request:json()      --[[ \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0442\u0437\u044b\u0432\u0430]]     place['id'] = uuid.str()     place['coordinates'] = obj['coordinates']     place['comment'] = obj['comment']      --[[         \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b     ]]     local t, err = box.space.geo:frommap(place)     if err ~= nil then         log.error(tostring(err))         return {code=503, body=tostring(err)}     end     --[[         \u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442     ]]     box.space.geo:insert(t)      return { body=json.encode({place}) } end  --[[     \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u043a\u0430\u0440\u0442\u0435     \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0435 \u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 ]] local function places(request)     local result = {}      local x1, y1, x2, y2 = unpack(json.decode(request:param(\"rect\")))      local limit = 1000     --[[         \u0418\u0442\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u043f\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0431\u043b\u0438\u0436\u0430\u0439\u0449\u0438\u0445 \u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432     ]]     for _, place in box.space.geo.index.geoidx:pairs({x1, y1, x2, y2}, {iterator='LE'}) do         -- \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u044a\u0435\u043a\u0442         local obj = {             ['id'] = place['id'],             coordinates = place['coordinates'],             comment = place['comment'],         }         table.insert(result, obj)         limit = limit - 1         if limit == 0 then             break         end     end     return {code=200,             body=json.encode(result)} end  --[[     \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043e\u0442\u0437\u044b\u0432\u043e\u0432 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435 ]] box.schema.space.create('geo', {if_not_exists=true}) box.space.geo:format({         {name=\"id\", type=\"string\"},         {name=\"coordinates\", type=\"array\"},         {name=\"comment\", type=\"string\"}, }) --[[ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 ]] box.space.geo:create_index('primary', {                                 parts={{field=\"id\", type=\"string\"}},                                 type = 'TREE',                                 if_not_exists=true,}) --[[ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0434\u0435\u043a\u0441 \u0434\u043b\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 ]] box.space.geo:create_index('geoidx', {                                 parts = {{ field=\"coordinates\", type='array'} },                                 type = 'RTREE', unique = false,                                 if_not_exists=true,})  --[[ \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c http \u0441\u0435\u0440\u0432\u0438\u0441 ]] local httpd = require('http.server').new('0.0.0.0', 8080) local router = require('http.router').new() httpd:set_router(router) router:route({path=\"\/\"}, index) router:route({path=\"\/new\"}, newplace) router:route({path=\"\/list\"}, places)  httpd:start()<\/code><\/pre>\n<\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/574542\/\"> https:\/\/habr.com\/ru\/articles\/574542\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><img loading=\"lazy\" decoding=\"async\" height=\"1\" src=\"https:\/\/top-fwz1.mail.ru\/counter?id=3200881;js=na\" style=\"display:none;\" width=\"1\"><img loading=\"lazy\" decoding=\"async\" height=\"1\" src=\"https:\/\/www.facebook.com\/tr?id=1220899431627792&amp;ev=PageView&amp;noscript=1\" style=\"display:none;\" width=\"1\"><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/92\/ed\/vv\/92edvvnp--vq2qd9gawm9zdbtiy.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/92\/ed\/vv\/92edvvnp--vq2qd9gawm9zdbtiy.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u042f\u0434\u0440\u043e Tarantool-\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 C, \u0430 \u0432\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0430 Lua. \u042d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u043d\u043e \u0438 \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Tarantool, \u043d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432\u0441\u0435\u0433\u043e \u0442\u0440\u0438 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 \u043a\u043e\u0434\u0430 \u043d\u0430 Lua. \u0410 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 Golang. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0435\u0449\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u044f \u0434\u0430\u044e \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043d\u0430 Python. \u0427\u0442\u043e \u0437\u0430 \u043f\u0440\u043e\u0435\u043a\u0442? \u0414\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043a\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435: \u0434\u043e\u043c, \u0440\u0430\u0431\u043e\u0442\u0430, \u043f\u0435\u0440\u0432\u043e\u0435 \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u0435, \u043f\u0435\u0440\u0432\u044b\u0439 Hello World, \u043f\u0435\u0440\u0432\u044b\u0439 &#171;too long wal write&#187; Tarantool.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-404999","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/404999","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=404999"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/404999\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=404999"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=404999"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=404999"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}