-
Notifications
You must be signed in to change notification settings - Fork 60
Add: Redis Geospatial Command Stages #328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
0a0d12b
add: redis geospatial stages
UdeshyaDhungana e7f7f51
- Initial proposition for redis/geospatial challenge
UdeshyaDhungana 314fced
Merge branch 'main' into redis-geospatial
UdeshyaDhungana ea695bb
- Apply requested changes
UdeshyaDhungana 974c132
Remove merge conflict
UdeshyaDhungana 98b4c6e
fix: update requested changes
UdeshyaDhungana fabccb8
fix: grammar
UdeshyaDhungana 78d1c0f
fix: typos
UdeshyaDhungana e5ff7a8
fix: description
UdeshyaDhungana db308e3
fix: typo
UdeshyaDhungana f613c8f
fix: update tester description for ck3
UdeshyaDhungana eac6dc4
Fix: update instructions; fix grammar
UdeshyaDhungana 7a6f6b0
Reorganize and reorder stages
UdeshyaDhungana bbf188f
- Restructured stages
UdeshyaDhungana f4af75c
fix: typos and add context
UdeshyaDhungana 29e33a1
apply suggsted changes
UdeshyaDhungana 9a6ec4c
Update geospatial stage description for the GEOADD command and its us…
rohitpaulk 87c039a
Update geospatial stage to clarify latitude and longitude validation …
rohitpaulk 43bd469
Update geospatial-01-zt4.md to remove reference to sorted set in GEOA…
rohitpaulk af148c6
Update geospatial stage descriptions with prerequisites and implement…
rohitpaulk bccffba
Refactor location scoring section and update algorithm description in…
rohitpaulk 21b4c0c
Update geospatial stage description with clearer RESP string referenc…
rohitpaulk 182e0d2
Refactor geospatial stage description for clarity and conciseness.
rohitpaulk ae84812
Fix typos and improve clarity in geospatial stage description for GEO…
rohitpaulk c1e00ac
Update geospatial stage description for GEOSEARCH command usage and e…
rohitpaulk fdda190
resolve merge conflicts
UdeshyaDhungana File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
In this stage, you'll add support for responding to the `GEOADD` command. | ||
|
||
### Extension prerequisites | ||
|
||
This stage depends on the [**Sorted Sets**](https://redis.io/docs/latest/data-types/sorted-sets/) extension. Before attempting this extension, please make sure you've completed the Sorted Sets extension. | ||
|
||
### The `GEOADD` command | ||
|
||
The [`GEOADD` command](https://redis.io/docs/latest/commands/geoadd/) adds a location (with longitude, latitude, and name) to a key. | ||
|
||
Example usage: | ||
|
||
```bash | ||
> GEOADD places -0.0884948 51.506479 "London" | ||
(integer) 1 | ||
``` | ||
|
||
The arguments `GEOADD` accepts are: | ||
|
||
1. `key`: The key to store the location in. | ||
2. `longitude`: The longitude of the location. | ||
3. `latitude`: The latitude of the location. | ||
4. `member`: The name of the location. | ||
|
||
It returns the count of elements added, encoded as a RESP Integer. | ||
|
||
In this stage, you'll only implement the response to the `GEOADD` command. We'll get to validating arguments and storing locations in later stages. | ||
|
||
### Tests | ||
|
||
The tester will execute your program like this: | ||
|
||
```bash | ||
$ ./your_program.sh | ||
``` | ||
|
||
It will then send a `GEOADD` command: | ||
|
||
```bash | ||
$ redis-cli GEOADD places 11.5030378 48.164271 Munich | ||
``` | ||
|
||
The tester will expect the response to be `:1\r\n`, which is 1 (number of locations added) encoded as a RESP integer. | ||
|
||
### Notes | ||
|
||
- In this stage, you only need to implement responding to the `GEOADD` command. We'll get to validating arguments and storing locations in later stages. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
In this stage, you'll add support for validating the latitude and longitude values provided in a `GEOADD` command. | ||
|
||
### Validating latitude and longitude values | ||
|
||
The latitude and longitude values used in the `GEOADD` command should be in a certain range as per [EPSG:3857](https://epsg.io/3857). | ||
|
||
- Valid longitudes are from -180° to +180° | ||
- Both these limits are inclusive, so -180° and +180° are both valid. | ||
- Valid latitudes are from -85.05112878° to +85.05112878° | ||
- Both of these limits are inclusive, so -85.05112878° and +85.05112878° are both valid. | ||
- The reason these limits are not -/+90° is because of the [Web Mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection) that Redis uses. | ||
|
||
If either of these values aren't within the appropriate range, `GEOADD` returns an error. Examples: | ||
|
||
```bash | ||
# Invalid latitude | ||
> GEOADD places 180 90 test1 | ||
(error) ERR invalid longitude,latitude pair 180.000000,90.000000 | ||
|
||
# Invalid longitude | ||
> GEOADD places 181 0.3 test2 | ||
(error) ERR invalid longitude,latitude pair 181.000000,0.300000 | ||
``` | ||
|
||
In this stage, you'll implement validating latitude and longitude values and returning error messages as shown above. The tester is lenient with error message formats, so you don't have to use the exact error message format mentioned above. | ||
|
||
### Tests | ||
|
||
The tester will execute your program like this: | ||
|
||
```bash | ||
$ ./your_program.sh | ||
``` | ||
|
||
It will then send multiple `GEOADD` commands. | ||
|
||
If the coordinates are invalid, it will expect an error response. For example: | ||
|
||
```bash | ||
# Expecting error | ||
$ redis-cli GEOADD location_key 200 100 foo | ||
(error) ERR invalid longitude,latitude pair 200,100 | ||
``` | ||
|
||
The returned value must: | ||
|
||
- Be a [RESP simple error](https://redis.io/docs/latest/develop/reference/protocol-spec/#simple-errors) i.e. start with `-` and end with `\r\n` | ||
- The error message must start with `ERR`, like standard Redis error messages | ||
- The error message must contain the word "latitude" if the latitude is invalid | ||
- The error message must contain the word "longitude" if the longitude is invalid | ||
|
||
For example, if the latitude is invalid, valid error messages that the tester will accept are: | ||
|
||
```bash | ||
-ERR invalid latitude argument\r\n | ||
-ERR invalid latitude value\r\n | ||
-ERR latitude value (200.0) is invalid\r\n | ||
``` | ||
|
||
### Notes | ||
|
||
- You don't need to implement storing locations yet, we'll get to that in later stages. | ||
- The boundary of latitude are clipped at -/+85.05112878° instead of -/+90°. This is because of the [Web Mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection) that Redis uses. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
In this stage, you'll add support for storing locations in a sorted set. | ||
|
||
### Storing locations in sorted set | ||
|
||
The locations added using the `GEOADD` command are stored in a sorted set. Redis internally calculates a score for the specified location using a location's latitude and longitude. | ||
|
||
For example, the following two commands are equivalent in Redis. | ||
|
||
```bash | ||
# Adding a location | ||
$ redis-cli GEOADD places_key 2.2944692 48.8584625 location | ||
|
||
# This command is equivalent to the command above | ||
$ redis-cli ZADD places_key 3663832614298053 location | ||
``` | ||
|
||
In this stage, you'll implement adding locations to a sorted set when a `GEOADD` command is run. | ||
|
||
You can hardcode the score to be 0 for now, we'll get to calculating the score in later stages. | ||
|
||
### Tests | ||
|
||
The tester will execute your program like this: | ||
|
||
```bash | ||
$ ./your_program.sh | ||
``` | ||
|
||
It will then send a `GEOADD` command: | ||
|
||
```bash | ||
$ redis-cli GEOADD places 2.2944692 48.8584625 Paris | ||
# Expect: (integer) 1 | ||
``` | ||
|
||
The tester will then send a `ZRANGE` command to validate that the location was added to the sorted set: | ||
|
||
```bash | ||
$ redis-cli ZRANGE places 0 -1 | ||
# Expect RESP Array: ["Paris"] | ||
``` | ||
|
||
### Notes | ||
|
||
- In this stage, you can hardcode the score of the location to be 0. We'll get to calculating the value of score using latitude and longitude in later stages. | ||
- The implementation of the `ZRANGE` command is covered in the sorted sets extension. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
In this stage, you'll add support for calculating the score of a location. | ||
|
||
### Location scores | ||
|
||
To store locations in a sorted set, Redis converts latitude and longitude values to a single "score". | ||
|
||
We've created a [GitHub repository](https://github.com/codecrafters-io/redis-geocoding-algorithm) that explains how this conversion is done. It includes: | ||
|
||
- A description of the algorithm used, along with pseudocode | ||
- Python code that implements the algorithm | ||
- A set of locations & scores to test against | ||
|
||
Here's the [repository link](https://github.com/codecrafters-io/redis-geocoding-algorithm). | ||
|
||
### Tests | ||
|
||
The tester will execute your program like this: | ||
|
||
```bash | ||
$ ./your_program.sh | ||
``` | ||
|
||
It will then send multiple `GEOADD` commands: | ||
|
||
```bash | ||
$ redis-cli GEOADD places 2.2944692 48.8584625 Paris | ||
# Expect: (integer) 1 | ||
$ redis-cli GEOADD places -0.127758 51.507351 London | ||
# Expect: (integer) 1 | ||
``` | ||
|
||
The tester will validate that scores are calculated correctly by sending multiple `ZSCORE` commands: | ||
|
||
```bash | ||
$ redis-cli ZSCORE places Paris | ||
# Expecting bulk string: "3663832614298053" | ||
``` | ||
|
||
The calculated scores must match the expected values as described in [this repository](https://github.com/codecrafters-io/redis-geocoding-algorithm). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
In this stage, you'll add support for responding to the `GEOPOS` command. | ||
|
||
### The `GEOPOS` command | ||
|
||
The `GEOPOS` command returns the longitude and latitude of the specified location. | ||
|
||
Example usage: | ||
|
||
```bash | ||
> GEOADD places -0.0884948 51.506479 "London" | ||
> GEOADD places 11.5030378 48.164271 "Munich" | ||
|
||
> GEOPOS places London | ||
1) 1) "-0.08849412202835083" | ||
2) "51.50647814139934" | ||
|
||
> GEOPOS places Munich | ||
1) 1) "11.503036916255951" | ||
2) "48.16427086232978" | ||
``` | ||
|
||
It returns an array with one entry for each location requested. | ||
|
||
- If the key does not exist, an empty array is returned `(*0\r\n)` | ||
- If a location exists under the key, its entry is an array of two items: | ||
- Longitude (Encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings)) | ||
- Latitude (Encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings)) | ||
- If a location doesn’t exist, the entry is a [null bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#null-bulk-strings) `($-1\r\n)`. | ||
|
||
To return the latitude and longitude values, Redis decodes the "score" back to latitude and longitude values. We'll cover this process in later stages, for now you can hardcode the returned latitude and longitude values to be 0 (or any number). | ||
|
||
### Tests | ||
|
||
The tester will execute your program like this: | ||
|
||
```bash | ||
$ ./your_program.sh | ||
``` | ||
|
||
It will then add multiple locations using the `GEOADD` command. | ||
|
||
```bash | ||
$ redis-cli | ||
> GEOADD location_key -0.0884948 51.506479 "London" | ||
# Expect: (integer) 1 | ||
> GEOADD location_key 11.5030378 48.164271 "Munich" | ||
# Expect: (integer) 1 | ||
``` | ||
|
||
The tester will then send multiple `GEOPOS` commands: | ||
|
||
```bash | ||
> GEOPOS location_key London Munich | ||
# Expecting: [["0", "0"], ["0", "0"]], encoded as "*2\r\n$1\r\n0\r\n$1\r\n0\r\n$1\r\n0\r\n$1\r\n0\r\n" | ||
> GEOPOS location_key missing_location | ||
# Expecting: [nil], encoded as "*1\r\n$-1\r\n" | ||
``` | ||
|
||
The tester will assert that: | ||
|
||
- The response is a RESP array that contains as many elements as the number of locations requested | ||
- For each location requested: | ||
- If the location exists: | ||
- The corresponding element is a RESP array with two elements (i.e. longitude and latitude) | ||
- Both elements are "0" (or any other valid floating point number), encoded as a RESP bulk string | ||
- If the location doesn't exist: | ||
- The corresponding element is a [null bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#null-bulk-strings) `($-1\r\n)`. | ||
|
||
The tester will also send a `GEOPOS` command using a key that doesn't exist: | ||
|
||
```bash | ||
> GEOPOS missing_key Foo | ||
# Expecting: [], encoded as "*0\r\n" | ||
``` | ||
|
||
It will expect the response to be an empty RESP array, which is encoded as `*0\r\n`. | ||
|
||
### Notes | ||
|
||
- In this stage, you can hardcode the returned latitude and longitude values to be 0 (or any other valid floating point number). We'll get to testing actual latitude and longitude values in later stages. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.