You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In this stage, you'll add support for responding to the `GEOADD` command.
2
+
3
+
### Extension prerequisites
4
+
5
+
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.
6
+
7
+
### The `GEOADD` command
8
+
9
+
The [`GEOADD` command](https://redis.io/docs/latest/commands/geoadd/) adds a location (with longitude, latitude, and name) to a key.
10
+
11
+
Example usage:
12
+
13
+
```bash
14
+
> GEOADD places -0.0884948 51.506479 "London"
15
+
(integer) 1
16
+
```
17
+
18
+
The arguments `GEOADD` accepts are:
19
+
20
+
1.`key`: The key to store the location in.
21
+
2.`longitude`: The longitude of the location.
22
+
3.`latitude`: The latitude of the location.
23
+
4.`member`: The name of the location.
24
+
25
+
It returns the count of elements added, encoded as a RESP Integer.
26
+
27
+
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.
The tester will expect the response to be `:1\r\n`, which is 1 (number of locations added) encoded as a RESP integer.
44
+
45
+
### Notes
46
+
47
+
- 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.
In this stage, you'll add support for validating the latitude and longitude values provided in a `GEOADD` command.
2
+
3
+
### Validating latitude and longitude values
4
+
5
+
The latitude and longitude values used in the `GEOADD` command should be in a certain range as per [EPSG:3857](https://epsg.io/3857).
6
+
7
+
- Valid longitudes are from -180° to +180°
8
+
- Both these limits are inclusive, so -180° and +180° are both valid.
9
+
- Valid latitudes are from -85.05112878° to +85.05112878°
10
+
- Both of these limits are inclusive, so -85.05112878° and +85.05112878° are both valid.
11
+
- 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.
12
+
13
+
If either of these values aren't within the appropriate range, `GEOADD` returns an error. Examples:
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.
26
+
27
+
### Tests
28
+
29
+
The tester will execute your program like this:
30
+
31
+
```bash
32
+
$ ./your_program.sh
33
+
```
34
+
35
+
It will then send multiple `GEOADD` commands.
36
+
37
+
If the coordinates are invalid, it will expect an error response. For example:
- 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`
48
+
- The error message must start with `ERR`, like standard Redis error messages
49
+
- The error message must contain the word "latitude" if the latitude is invalid
50
+
- The error message must contain the word "longitude" if the longitude is invalid
51
+
52
+
For example, if the latitude is invalid, valid error messages that the tester will accept are:
53
+
54
+
```bash
55
+
-ERR invalid latitude argument\r\n
56
+
-ERR invalid latitude value\r\n
57
+
-ERR latitude value (200.0) is invalid\r\n
58
+
```
59
+
60
+
### Notes
61
+
62
+
- You don't need to implement storing locations yet, we'll get to that in later stages.
63
+
- 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.
In this stage, you'll add support for storing locations in a sorted set.
2
+
3
+
### Storing locations in sorted set
4
+
5
+
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.
6
+
7
+
For example, the following two commands are equivalent in Redis.
In this stage, you'll implement adding locations to a sorted set when a `GEOADD` command is run.
18
+
19
+
You can hardcode the score to be 0 for now, we'll get to calculating the score in later stages.
20
+
21
+
### Tests
22
+
23
+
The tester will execute your program like this:
24
+
25
+
```bash
26
+
$ ./your_program.sh
27
+
```
28
+
29
+
It will then send a `GEOADD` command:
30
+
31
+
```bash
32
+
$ redis-cli GEOADD places 2.2944692 48.8584625 Paris
33
+
# Expect: (integer) 1
34
+
```
35
+
36
+
The tester will then send a `ZRANGE` command to validate that the location was added to the sorted set:
37
+
38
+
```bash
39
+
$ redis-cli ZRANGE places 0 -1
40
+
# Expect RESP Array: ["Paris"]
41
+
```
42
+
43
+
### Notes
44
+
45
+
- 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.
46
+
- The implementation of the `ZRANGE` command is covered in the sorted sets extension.
In this stage, you'll add support for calculating the score of a location.
2
+
3
+
### Location scores
4
+
5
+
To store locations in a sorted set, Redis converts latitude and longitude values to a single "score".
6
+
7
+
We've created a [GitHub repository](https://github.com/codecrafters-io/redis-geocoding-algorithm) that explains how this conversion is done. It includes:
8
+
9
+
- A description of the algorithm used, along with pseudocode
10
+
- Python code that implements the algorithm
11
+
- A set of locations & scores to test against
12
+
13
+
Here's the [repository link](https://github.com/codecrafters-io/redis-geocoding-algorithm).
14
+
15
+
### Tests
16
+
17
+
The tester will execute your program like this:
18
+
19
+
```bash
20
+
$ ./your_program.sh
21
+
```
22
+
23
+
It will then send multiple `GEOADD` commands:
24
+
25
+
```bash
26
+
$ redis-cli GEOADD places 2.2944692 48.8584625 Paris
27
+
# Expect: (integer) 1
28
+
$ redis-cli GEOADD places -0.127758 51.507351 London
29
+
# Expect: (integer) 1
30
+
```
31
+
32
+
The tester will validate that scores are calculated correctly by sending multiple `ZSCORE` commands:
33
+
34
+
```bash
35
+
$ redis-cli ZSCORE places Paris
36
+
# Expecting bulk string: "3663832614298053"
37
+
```
38
+
39
+
The calculated scores must match the expected values as described in [this repository](https://github.com/codecrafters-io/redis-geocoding-algorithm).
In this stage, you'll add support for responding to the `GEOPOS` command.
2
+
3
+
### The `GEOPOS` command
4
+
5
+
The `GEOPOS` command returns the longitude and latitude of the specified location.
6
+
7
+
Example usage:
8
+
9
+
```bash
10
+
> GEOADD places -0.0884948 51.506479 "London"
11
+
> GEOADD places 11.5030378 48.164271 "Munich"
12
+
13
+
> GEOPOS places London
14
+
1) 1) "-0.08849412202835083"
15
+
2) "51.50647814139934"
16
+
17
+
> GEOPOS places Munich
18
+
1) 1) "11.503036916255951"
19
+
2) "48.16427086232978"
20
+
```
21
+
22
+
It returns an array with one entry for each location requested.
23
+
24
+
- If the key does not exist, an empty array is returned `(*0\r\n)`
25
+
- If a location exists under the key, its entry is an array of two items:
26
+
- Longitude (Encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings))
27
+
- Latitude (Encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings))
28
+
- 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)`.
29
+
30
+
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).
31
+
32
+
### Tests
33
+
34
+
The tester will execute your program like this:
35
+
36
+
```bash
37
+
$ ./your_program.sh
38
+
```
39
+
40
+
It will then add multiple locations using the `GEOADD` command.
The tester will then send multiple `GEOPOS` commands:
51
+
52
+
```bash
53
+
> GEOPOS location_key London Munich
54
+
# 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"
55
+
> GEOPOS location_key missing_location
56
+
# Expecting: [nil], encoded as "*1\r\n$-1\r\n"
57
+
```
58
+
59
+
The tester will assert that:
60
+
61
+
- The response is a RESP array that contains as many elements as the number of locations requested
62
+
- For each location requested:
63
+
- If the location exists:
64
+
- The corresponding element is a RESP array with two elements (i.e. longitude and latitude)
65
+
- Both elements are "0" (or any other valid floating point number), encoded as a RESP bulk string
66
+
- If the location doesn't exist:
67
+
- The corresponding element is a [null bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#null-bulk-strings)`($-1\r\n)`.
68
+
69
+
The tester will also send a `GEOPOS` command using a key that doesn't exist:
70
+
71
+
```bash
72
+
> GEOPOS missing_key Foo
73
+
# Expecting: [], encoded as "*0\r\n"
74
+
```
75
+
76
+
It will expect the response to be an empty RESP array, which is encoded as `*0\r\n`.
77
+
78
+
### Notes
79
+
80
+
- 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.
0 commit comments