{"id":19839331,"url":"https://github.com/redislabs/geo.lua","last_synced_at":"2025-05-01T18:31:57.994Z","repository":{"id":141980471,"uuid":"52166634","full_name":"RedisLabs/geo.lua","owner":"RedisLabs","description":"A helper library for Redis geospatial indices","archived":false,"fork":false,"pushed_at":"2017-09-26T15:17:17.000Z","size":22,"stargazers_count":146,"open_issues_count":4,"forks_count":22,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-06T16:54:24.645Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RedisLabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-02-20T17:47:48.000Z","updated_at":"2024-05-18T14:22:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"e3e70951-f67e-49d7-aa67-3f36eb813ebf","html_url":"https://github.com/RedisLabs/geo.lua","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedisLabs%2Fgeo.lua","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedisLabs%2Fgeo.lua/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedisLabs%2Fgeo.lua/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedisLabs%2Fgeo.lua/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RedisLabs","download_url":"https://codeload.github.com/RedisLabs/geo.lua/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251924840,"owners_count":21666044,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-11-12T12:21:50.389Z","updated_at":"2025-05-01T18:31:57.684Z","avatar_url":"https://github.com/RedisLabs.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"geo.lua - helper library for Redis geospatial indices :earth_africa:\n===\n\nThis is a Lua library containing miscellaneous geospatial helper routines for use with [Redis]. It requires the [Redis GEO API], available from v3.2.\n\nIn broad strokes, the library provides:\n* [Polygon searches](#GEOMETRYFILTER) on geoset members\n* Navigational information such as [bearing](#GEOBEARING) and [path length](#GEOPATHLEN)\n* GeoJSON [decoding](#GEOJSONADD) and [encoding](#GEOJSONENCODE)\n* A playground for testing experimental geospatial APIs\n\nThe library is strictly :straight_ruler: metric, sorry.\n![Metric system adoption worldwide](https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Metric_system_adoption_map.svg/2000px-Metric_system_adoption_map.svg.png)\n\nUsing geo.lua\n---\nThe library is an ordinary Redis Lua script - use [`EVAL`] or [`EVALSHA`] to call it. The following example demonstrates usage from the prompt:\n\n````Bash\n$ redis-cli SCRIPT LOAD \"$(cat geo.lua)\"\n\"fd07...\"\n$ redis-cli EVALSHA fd07... 0 help\n 1) \"geo.lua (0.1.5): A helper library for Redis geospatial indices\"\n ...\n````\n\nLibrary API\n---\n\n### GEO API completeness\n\n\u003ca name=\"GEOBEARING\"\u003e\u003c/a\u003e\n#### GEOBEARING KEYS[1] geoset ARGV[2] member1 3] member2\nReturn the initial and final bearing between two members.\n\u003e Time complexity: O(1).\n\nFor information about the calculation refer to  http://mathforum.org/library/drmath/view/55417.html.\n\n**Return:** Array reply, specifically the initial and final bearings.\n\n\u003ca name=\"GEOPATHLEN\"\u003e\u003c/a\u003e\n#### GEOPATHLEN KEYS[1] geoset ARGV[2] member [...]\nThe length of a path between members.\n\u003e Time complexity: O(N) where N is the number of members.\n\n**Note:** This is basically a variadic form for [`GEODIST`].\n\n**Return:** String reply, specifically the length in meters.\n\n\u003ca name=\"GEODEL\"\u003e\u003c/a\u003e\n#### GEODEL KEYS[1] geoset ARGV[2] member [...]\nDelete members from a geoset.\n\u003e Time complexity: O(M*log(N)) with N being the number of elements in the geoset and M the number of elements to be removed.\n\nThis command is an alias for [`ZREM`] to disprove the [GEO incompleteness theorem](https://twitter.com/monadic/status/690889597866393600). Technically it should be called `GEOREM` however.\n\n**Return:** Integer reply, specifically the number of members actually deleted.\n\n### 2D geometries and polygon search\nRedis' geosets allow [storing](http://redis.io/commands/geoadd) (and [querying](http://redis.io/commands/georadius)) of `Point` (2D, x/y, longitude \u0026 latitude) geometries. Other geometries can be stored serialized (using [msgpack](http://msgpack.org/index.html)) in a Redis Hash data structure - the geomash. The geoset and the geomash are used for storing geometries in the following manner:\n\n| Geometry             | Storage | `GEOMETRYADD` | `GEOMETRYGET` | `GEOMETRYFILTER` | `GEOJSONADD`\n| :---                 | :---    | :---:         | :---:         | :---:            | :---:\n| `Point`              | geoset  | N/A           | N/A           | No               | Yes\n| `Polygon`            | geomash | Yes           | Yes           | Yes              | Yes\n| `MultiPolygon`       | geomash | TODO          | TODO          | TODO             | RODO\n| `MultiPoint`         | TODO    | TODO          | TODO          | No               | TODO\n| `LineString`         | TODO    | TODO          | TODO          | TODO             | TODO\n| `MultiLineString`    | TODO    | TODO          | TODO          | TODO             | TODO\n| `GeometryCollection` | TODO    | TODO          | TODO          | TODO             | TODO\n\n\u003ca name=\"GEOMETRYADD\"\u003e\u003c/a\u003e\n#### GEOMETRYADD KEYS[1] geomash ARGV[2] geometry-type 3] id 4..] \u003cgeometry data\u003e\nUpsert a single geometry to a geomash.\n\u003e Time complexity:\n\n`ARGV[4]` and above describe the geometry. Depending on the geometry's type:\n  * `POLYGON` - each pair of ARGVs (e.g., 4 and 5, 6 and 7, ...) represent the coordinates of a vertex (longitude and latitude). A minimum of 4 vertices are required to define a polygon, with the first and last vertices being equal (a LineRing).\n\n**Note:** there is no `GEOMETYREM`, use [`HDEL`](http://redis.io/commands/hdel) instead.\n\n**Return:** Integer reply, specifically 0 if updated and 1 if added.\n\n\u003ca name=\"GEOMETRYGET\"\u003e\u003c/a\u003e\n#### GEOMETRYGET KEYS[1] geomash ARGV[a] [WITHPERIMETER|WITHBOX|WITHCIRCLE] [...] ARGV[2] id  [...]\nReturns geometries' coordinates.\n\u003e Time complexity:\n\nThe reply can be enriched with meta data about the geometry. The following sub-commands are supported, depending on the type of geometry.\n  * `WITHPERIMETER`: For `Polygon`, The total length of edges\n  * `WITHBOX`: The bounding box of the geometry\n  * `WITHCIRCLE`: The bounding circle of the geometry\n\n**Return:** Array reply, specifically:`\n  * The geometry's type\n  * The geometry's coordinates\n  * When called with `WITHPERIMETER`, the total length of edges\n  * When called with `WITHBOX`, the minimum and maximum coordinates of the bounding box, as well as it's bounding circle's radius\n  * When called with `WITHCIRCLE`, the center coordinates and radius of bounding circle\n\n\u003ca name=\"GEOMETRYFILTER\"\u003e\u003c/a\u003e\n#### GEOMETRYFILTER KEYS[1] geoset 2] geomash a] [target] ARGV[a] [STORE|WITHCOORD] [...] ARGV[2] id\nSearch for geoset members inside a geometry.\n\u003e Time complexity:\n\nThis command performs a [`GEORADIUS`] search that contains the geometry's bounding box. The results are then filtered using a Point-In-Polygon (PIP) algorithm ([source](https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html#The C Code)).\n\nThe following sub-commands are supported:\n * `STORE`: Stores the search results in the target geoset\n * `WITHCOORD`: Returns the members' coordinates as well\n\n**Return:** Array reply, specifically the members and their coordinates (if called with `WITHCOORD`). When the `STORE` directive is used, the reply is an Integer that indicates the number of members that were upserted to the target geoset.\n\n### GeoJSON\nA minimal implementation of the [spec's v1.0](http://geojson.org/geojson-spec.html) for decoding and encoding geoset and geomash members from/to `FeatureCollection`s and `Feature`s.\n\n\u003ca name=\"GEOJSONADD\"\u003e\u003c/a\u003e\n#### GEOJSONADD KEYS[1] geoset 2] geomash ARGV[1] GeoJSON\n\u003e Time complexity: O(log(N)) for each feature in the GeoJSON object, where N is the number of members in the geoset.\n\nUpsert points to the geoset, other geometries to the geomash. A valid input GeoJSON object must be `FeatureCollection`. Each `Feature`'s type must be `Point` or a `Polygon`, and the feature's properties must include a member named `id`.\n\n**Return:** Integer reply, specifically the number of features upserted.\n\n\u003ca name=\"GEOJSONENCODE\"\u003e\u003c/a\u003e\n#### GEOJSONENCODE KEYS[1] geoset ARGV[2] \u003cGEO command\u003e 3] [arg] [...]\n\u003e Time complexity: depends on the GEO command and its arguments.\n\nEncodes the reply of GEO commands as a GeoJSON object. Valid GEO commands are:\n* [`GEOHASH`]\n* [`GEOPOS`]\n* [`GEORADIUS`] and [`GEORADIUSBYMEMBER`]\n* [`GEOMETRYFILTER`]\n\n**Return:** String, specifically the reply of the GEO command encoded as a GeoJSON object.\n\n### Location updates\nImplements a real-time location tracking mechanism. Inspired by [Matt Stancliff @mattsta](https://matt.sh/redis-geo).\n\n\u003ca name=\"GEOTRACK\"\u003e\u003c/a\u003e\n#### GEOTRACK KEYS[1] geoset ARGV[2] longitude 3] latitude 4] member [...]\n\u003e Time complexity: O(log(N)+M+P) for each item added, where N is the number of elements in the geoset, M is the number of clients subscribed to the receiving channel and P is the total number of subscribed patterns (by any client).\n\n[`GEOADD`]s a member and [`PUBLISH`]s on channel `__geo:\u003cgeoset\u003e:\u003cmember\u003e` a message with the format of `\u003clongitude\u003e:\u003clatitude\u003e`.\n\nClients can track updates made to a specific member by subscribing to that member's channel (i.e. [`SUBSCRIBE`]`__geo:\u003cgeoset\u003e:\u003cmember\u003e`) or to all members updates (i.e. [`PSUBSCRIBE`]`__geo:\u003cgeoset\u003e:*`).\n\n**Return:** Integer reply, specifically the number of members upserted.\n\n### xyzsets\nRedis' geospatial indices only encode the longitude and latitude of members with no regard to their altitude. An xyzset uses two sorted sets, one as geoset and the other for storing altitudes.\n\n\u003ca name=\"GEOZADD\"\u003e\u003c/a\u003e\n#### GEOZADD KEYS[1] geoset 2] azset ARGV[2] logitude 3] latitude 4] altitude 5] member [...]\n\u003e Time complexity: O(log(N)) for each item added, where N is the number of elements in the geoset.\n\nUpsert members. Altitude is given as meters above (or below) sea level.\n\n**Return:** Integer reply, specifically the number of members upserted.\n\n\u003ca name=\"GEOZREM\"\u003e\u003c/a\u003e\n#### GEOZREM KEYS[1] geoset 2] azset ARGV[2] member [...]\n\u003e Time complexity: O(M*log(N)) with N being the number of elements in the geoset and M the number of elements to be removed.\n\nRemove members.\n\n**Return:** Integer reply, specifically the number of members actually deleted.\n\n\u003ca name=\"GEOZPOS\"\u003e\u003c/a\u003e  \n#### GEOZPOS KEYS[1] geoset 2] azset ARGV[2] member [...]\n\u003e Time complexity: O(log(N)) for each member requested, where N is the number of elements in the geoset.\n\nThe position of members in 3D.\n\n**Return:** Array reply, specifically the members and their positions.\n\n#### TODO: GEOZDIST\nReturns the distance between members.\n\n#### TODO: GEOZCYLINDER\nPerform cylinder-bound search.\n\n#### TODO: GEOZCYLINDERBYMEMBER\nPerform cylinder-bound search by member (a 20 characters command!).\n\n#### TODO: GEOZSPHERE\nUseful for directing air traffic and impact research (bombs, comets).\n\n#### TODO: GEOZCONE\nGood for comparing :alien: sightings vis a vis :cow: abduction data.\n\n### Motility\nStoring each member's vector in an additional hash data structure, where the field is the member's name and the value is the serialized vector (bearing \u0026 velocity).\n\n#### TODO: GEOMADD KEYS[1] geoset 2] vector hash ARGV[2] longitude 3] latitude 4] bearing 5] velocity 6] member [...]\n\nUpsert members. Bearing given in degrees, velocity in meters/second.\n\n#### TODO: GEOMREM KEYS[1] geoset 2] vector hash ARGV[2] member [...]\nRemove members.\n\n#### TODO: GEOMPOSWHEN KEYS[1] geoset 2] vector hash ARGV[2] seconds 3] member [...]\nProject members position in future or past.\n\n#### TODO: GEOMMEETWHENWHERE KEYS[1] geoset 2] vector hash ARGV[2] member1 3] member2\nHelp solving basic math exercises.\n\nLicense\n---\n3-Clause BSD.\n\nContributing\n---\n\nYou're encouraged to contribute to the open source geo.lua project. There are two ways you can do so.\n\n### Issues\n\nIf you encounter an issue while using the geo.lua library, please report it at the project's issues tracker. Feature suggestions are also welcome.\n\n### Pull request\n\nCode contributions to the geo.lua project can be made using pull requests. To submit a pull request:\n\n1. Fork this project.\n2. Make and commit your changes.\n3. Submit your changes as a pull request.\n\n[Redis]: http://redis.io\n[Redis GEO API]: (http://redis.io/commands#geo)\n[`GEOADD`]: (http://redis.io/commands/geoadd)\n[`GEODIST`]: (http://redis.io/commands/geodist)\n[`GEOHASH`]: (http://redis.io/commands/geohash)\n[`GEOPOS`]: (http://redis.io/commands/geopos)\n[`GEORADIUS`]: (http://redis.io/commands/georadius)\n[`GEORADIUSBYMEMBER`]: (http://redis.io/commands/georadiusbymember)\n[`EVAL`]: (http://redis.io/commands/eval)\n[`EVALSHA`]: (http://redis.io/commands/evalsha)\n[`PUBLISH`]: (http://redis.io/commands/publish)\n[`SUBSCRIBE`]: (http://redis.io/commands/subscribe)\n[`PSUBSCRIBE`]: (http://redis.io/commands/psubscribe)\n[`ZREM`]: (http://redis.io/commands/zrem)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredislabs%2Fgeo.lua","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredislabs%2Fgeo.lua","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredislabs%2Fgeo.lua/lists"}