{"id":13800885,"url":"https://github.com/armon/teles","last_synced_at":"2026-03-10T05:02:29.564Z","repository":{"id":5718608,"uuid":"6929880","full_name":"armon/teles","owner":"armon","description":"An Erlang network service for manipulating geographic data","archived":false,"fork":false,"pushed_at":"2016-07-22T23:05:44.000Z","size":441,"stargazers_count":15,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T19:32:24.103Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/armon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-11-29T22:45:50.000Z","updated_at":"2023-06-21T06:17:20.000Z","dependencies_parsed_at":"2022-09-09T13:11:06.725Z","dependency_job_id":null,"html_url":"https://github.com/armon/teles","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/armon/teles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armon%2Fteles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armon%2Fteles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armon%2Fteles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armon%2Fteles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/armon","download_url":"https://codeload.github.com/armon/teles/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armon%2Fteles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30325598,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T01:36:58.598Z","status":"online","status_checked_at":"2026-03-10T02:00:06.579Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T00:01:17.300Z","updated_at":"2026-03-10T05:02:29.535Z","avatar_url":"https://github.com/armon.png","language":"Erlang","readme":"Teles [![Build Status](https://travis-ci.org/armon/teles.png)](https://travis-ci.org/armon/teles)\n=====\n\nTeles is an Erlang network service for manipulating geographic data.\nSpecifically, it uses in-memory R*-trees to store and manipulate geo-spacial\nindexes. It can be used to quickly provide answers to geo-spacial queries\nthat are otherwise difficult or tedious to embed within an application.\n\nIt was originally written for targetting rewards at Kiip.\n\n\nFeatures\n--------\n\n* Scalable implementation allows for many connected\n  clients and concurrent queries\n* Uses R*-trees for efficient queries\n* Simple ASCII protocol\n* Relatively fast\n\n\nInstall\n-------\n\nDownload and build from source::\n\n    $ git clone https://armon@github.com/armon/teles.git\n    $ cd teles\n    $ make deps\n    $ make rel\n\nAt this point, rel/teles will contain a release build\n\n\nUsage\n-----\n\nTeles can be configured using the sys.config file.\nHere is an example configuration file:\n\n    [\n     {teles, [\n                {teles_agent_concurrency, 4},\n                {teles_port, 2856},\n                {teles_accept_pool, 8}\n            ]}\n    ].\n\n\nHere is a brief description of the configurations:\n\n* teles\\_agent\\_concurrency : This controls how many duplicate copies of data\n  is held. By having more than 1 R-tree, we can perform more queries in parallel.\n  This trade-off is made at the cost of memory utilization. If we have 4 agents,\n  then we can perform 4 queries at a time, and consequently use 4x the RAM. Additionally,\n  if an agent dies, recovery can be performed using another agent to avoid data loss. Sane\n  configurations are probably either 1 for no duplication, or the number of CPU's on the box\n  if memory allows.\n\n* teles\\_port : The port that teles listens on\n* teles\\_accept\\_pool : The number of processes accepting new connections. Default of 8\n  probably does not need to be modified.\n\n\nProtocol\n--------\n\nBy default, Teles will listen for TCP connections on port 2956.\nIt uses a simple ASCII protocol that is meant to be fairly human readable,\nwhile being easy to parse.\n\nEach command is newline, and optionally carriage return delimited:\n\n    cmd [args][\\r]\\n\n\nWe start each line by specifying a command, providing optional arguments,\nand ending the line in a newline (carriage return is optional).\n\nThere are a total of 14 commands:\n\n* use space - Sets the namespace of the connection\n* create space - Creates a new namespace. These are for logical seperation of data\n  similar to a new 'database' for an RDBMS\n* delete space - Deletes a namespace\n* list spaces - Lists all available name spaces\n* in - This is a command prefix, and executes the next command in a specific namespace\n* add object - Adds a named object to a namespace. An object has an opaque name (Teles doesn't care),\nand can be associated with various geospacial points.\n* delete object - Deletes an object\n* list objects - Lists all the objects in the namespace\n* list associations - Lists all the points associated with an object\n* associate point - Associates an object with a Lat / Lng point\n* disassociate - Disassociations an object with a Lat / Lng point\n* query within - Queries within a search box for any objects\n* query nearest - Queries for the K nearest objects to a given Lat / Lng\n* query around - Queries around a Lat / Lng for a given distance for objects\n\n\nFor the ``use`` command, we only space the name of a space to use:\n\n    use cities\n\nThis will either return \"Done\\n\" on success or will return \"Space does not exist\\n\",\nif a space which is not yet created is specified.\n\nThe ``create space`` command just takes the name of a space, which can\nalready exist, and creates it. It always returns \"Done\\n\":\n\n    \u003e create space states\n    Done\n\nIssuing a ``create space`` also causes that space to be used. For this reason, if you\nwant to use a space and ensure it exists, it is safe to always use create.\n\nThe ``delete space`` command is like ``create space`` but may return \"Space does not exist\".\n\nThe ``list spaces`` command takes no arguments but will list all the spaces in a\nSTART/END block like such:\n\n    \u003e list spaces\n    START\n    cities\n    states\n    testing\n    END\n\nThis format is common to all commands that may return a list of results.\n\nThe ``in`` command is not a command by itself, but it takes a space and a command\nand executes teh command in a given space. For example, to add an object to the 'cities' space,\nit is possible to do:\n\n    \u003e in cities add object sanfrancisco\n\nThis is an alternative do doing:\n\n    \u003e use cities\n    Done\n\n    \u003e add object sanfrancisco\n    Done\n\nThese are considered equivilent. However, some clients may prefer to use the ``in`` format\nas then a single connection can be used to issue commands to multiple spaces. It is possible\nto change the space of a connection at any time by doing ``use`` again.\n\nThe ``add object`` command takes an opaque name and always returns \"Done\\n\". The object may already\nexist. The name has no meaning to Teles and can be an application level ID.\n\nThe ``delete object`` command takes an opaque name and returns \"Done\\n\" if successful.\nIf the object does not exist, then it will return \"Object not found\\n\".\n\nThe ``list objects`` command takes no arguments but will list all the objects in the space.\nIt will also use a START/END block:\n\n    \u003e in cities list objects\n    START\n    sanfrancisco\n    portland\n    seattle\n    END\n\nThe ``list associations with`` command takes an object as an argument and lists all the associated\npoints in a START/END block:\n\n    \u003e in people list associations with jane\n    START\n    GID=3059837609 lat=38.8730 lng=-118.3570\n    GID=3277219006 lat=40.1230 lng=-120.5120\n    END\n\nThe results are a single row for each point (lat/lng) that the object is associated with.\nObjects can have a one-to-many mapping of points. For example, this could be all the places\nthat jane has visited. The GID is the Geometry ID, and it is used to remove associations.\n\nTo first create an association, the ``associate point \u003clat\u003e \u003clng\u003e with \u003cobj\u003e`` command is\nused. The latitude and longitude are given as decimal floating point representations, and\nthe object ID is also provide::\n\n    \u003e in people associate point 38.873 -118.357 with jane\n    Done\n\nIf an object does not exist, then \"Object not found\" will be returned.\nIf an object is already associated with the given point, nothing will change.\n\nRemoving an association is done with the ``disassociate`` command::\n\n    \u003e in people disassociate 3277219006 with jane\n    Done\n\nThis will disassociate jane with the GID (Geometry ID) 3277219006. These\ncan be found using list associations. This command can also return \"Object not found\\n\"\nor \"GID not associated\\n\"\n\nFinally, after objects are added, queries can be done to find all matching objects.\nThere are 3 types of queries: window, nearest, and around. The window query creates\na lat/lng box and finds all points inside. Nearest takes a point and finds the K nearest\nneighbors. Finally, around takes a point and searches for some distance around it.\n\nA window query is done by using ``query within``:\n\n    \u003e in people query within 40.123 45.451 -122.1 -120.3\n    START\n    mary\n    jane\n    joe\n    END\n\nThis will find all objects where latitude is between 40.123 and 45.451,\nand longitude is between -122.1 and -120.3.\n\nA nearest query is done by using ``query nearest``:\n\n    \u003e in people query nearest 5 to 40.11 -120.3\n    START\n    courtney\n    grantland\n    adam\n    amadeus\n    jack\n    END\n\nThis finds the 5 nearest objects to the point 40.11 -120.3.\n\nAn around query is done using ``query around``:\n\n    \u003e in cities query around 40.11 -120.3 for 15mi\n    START\n    sanfrancisco\n    oakland\n    marin\n    marin\n    dalycity\n    END\n\nThis finds all the objects within 15 miles of 40.11 / -120.3.\nTHe distance measure is expected to be in units of meters, however\nthe following suffixes are understood:\n\n* m: Meters      (1000m)\n* km: Kilometers (15km)\n* mi: Miles      (5mi)\n* y: Yard        (2000y)\n* ft: Feet       (5000ft)\n\nThere are also various error codes that are possible. If arguments\nare bad, the server can return: \"Client Error: Bad arguments\\n\".\nIf latitude or longitude is bad, then \"Client Error: Bad lat/lng format\\n\"\nmay be returned. Lastly commands that require a namespace (either through use\nof ``in`` or ``use space``) will return \"Client Error: Must use a namespace\\n\"\nif one is not provided.\n\n\nExample\n----------\n\nHere is an example of a client flow, assuming teles is\nrunning on the default port using just telnet::\n\n    $ telnet localhost 2856\n    \u003e list spaces\n    START\n    END\n\n    \u003e create space testing\n    Done\n\n    \u003e list spaces\n    START\n    testing\n    END\n\n    \u003e list objects\n    START\n    END\n\n    \u003e add object jill\n    Done\n\n    \u003e add object jack\n    Done\n\n    \u003e add object joe\n    Done\n\n    \u003e delete object joe\n    Done\n\n    \u003e list objects\n    START\n    jack\n    jill\n    END\n\n    \u003e associate point 40.123 -120.515 with jack\n    Done\n\n    \u003e associate point 40.123 -120.515 with jill\n    Done\n\n    \u003e list associations with jack\n    START\n    GID=2192486008 lat=40.1230 lng=-120.5150\n    END\n\n    \u003e disassociate 2192486008 with jack\n    Done\n\n    \u003e list associations with jack\n    START\n    END\n\n    \u003e query nearest 5 to 40.123 -120.515\n    START\n    jill\n    END\n\n    \u003e delete space testing\n    Done\n\n\nClients\n----------\nHere is a list of known client implementations:\n\n* Python : https://github.com/armon/pyteles\n* Go : https://github.com/geetarista/go-teles\n\nHere is a list of \"best-practices\" for client implementations:\n\n* Maintain a set of open connections to the server to minimize connection time\n* Doing a 'use space' at the start of the connection avoids the need to\n  specify 'in \u003cspace\u003e' before each connection\n\nPerformance\n-----------\n\nCasual testing was performed on a 2012 Macbook Pro with default configurations,\nand a concurrency of 4 per space. For a space with 370,000 objects, average insert\ntime was 500μs, resulting in an total of 2000 inserts per second. Performing ``query around``\nwith a random lat/lng and random distance between 1 and 100 miles took 300μs but with\nmutilple clients about 6000 QPS can be achieved. Lastly, doing ``query nearest`` with\na random lat/lng and between 1 and 50 neighbors took 1.6ms on average, and with 4 clients\n2400 QPS was possible.\n\n\nReferences\n----------\n\nPackages:\n\n* The R*-tree implemetation is from the [erl-rstar package](http://github.com/armon/erl-rstar).\n\nRelated works:\n\n* [R-trees: A dynamic index structure for spacial searching](http://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Guttman84.pdf)\n* [The R*-tree: An Efficient and Robust Access Method for Points and Rectangles](http://www.cs.ucr.edu/~tsotras/cs236/F11/rstar.pdf)\n* [Nearest Neighbor Queries](http://postgis.refractions.net/support/nearestneighbor.pdf)\n* [Enhanced Nearest Neighbor Search on the R-tree](http://www.cse.cuhk.edu.hk/~adafu/Pub/rtree.ps)\n\n","funding_links":[],"categories":["Geolocation"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farmon%2Fteles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farmon%2Fteles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farmon%2Fteles/lists"}