Skip to content

Commit 4057de1

Browse files
DOC-2761 relocated and filled out the content
1 parent b908c65 commit 4057de1

File tree

5 files changed

+289
-132
lines changed

5 files changed

+289
-132
lines changed

content/develop/interact/search-and-query/advanced-concepts/geo.md

Lines changed: 150 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,23 @@ weight: 14
1717
---
1818

1919
Redis Query Engine supports geospatial data. This feature
20-
lets you store geographical locations in the fields of JSON objects.
21-
You can then use queries to find the objects by their location.
20+
lets you store geographical locations and geometric shapes
21+
in the fields of JSON objects.
22+
23+
{{< note >}}Take care not to confuse the geospatial indexing
24+
features in Redis Query Engine with the
25+
[Geospatial data type]({{< relref "/develop/data-types/geospatial" >}})
26+
that Redis also supports. Although there are some similarities between
27+
these two features, the data type is intended for simpler use
28+
cases and doesn't have the range of format options and queries
29+
available in Redis Query Engine.
30+
{{< /note >}}
31+
32+
You can index these fields and use queries to find the objects
33+
by their location or the relationship of their shape to other shapes.
2234
For example, if you add the locations of a set of shops, you can
23-
find all the shops within 5km of a user's position.
35+
find all the shops within 5km of a user's position or determine
36+
which ones are within the boundary of a particular town.
2437

2538
Redis uses coordinate points to represent geospatial locations.
2639
You can store individual points but you can also
@@ -29,7 +42,7 @@ town, for example). You can query several types of interactions
2942
between points and shapes, such as whether a point lies within
3043
a shape or whether two shapes overlap.
3144

32-
You can interpret coordinates either as geographical longitude
45+
Redis can interpret coordinates either as geographical longitude
3346
and latitude or as Cartesian coordinates on a flat plane.
3447
Geographical coordinates are ideal for large real-world locations
3548
and areas (such as towns and countries). Cartesian coordinates
@@ -38,16 +51,142 @@ or for games, simulations, and other artificial scenarios.
3851

3952
## Storing geospatial data
4053

54+
Redis supports two different
55+
[schema types]({{< relref "/develop/interact/search-and-query/basic-constructs/field-and-type-options" >}})
56+
for geospatial data:
57+
58+
- [`GEO`](#geo): This uses a simple format where individual geospatial
59+
points are specified as numeric longitude-latitude pairs.
60+
61+
- [`GEOSHAPE`](#geoshape): [Redis Stack]({{< relref "/operate/oss_and_stack" >}}) also
62+
supports `GEOSHAPE` indexing in v7.2 and later.
63+
This uses a subset of the
64+
[Well-Known Text (WKT)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)
65+
format to specify both points and polygons using either geographical
66+
coordinates or Cartesian coordinates. A
67+
`GEOSHAPE` field supports more advanced queries than `GEO`,
68+
such as checking if one shape overlaps or contains another.
69+
70+
The sections below describe these schema types in more detail.
71+
72+
## `GEO`
73+
74+
A `GEO` index lets you represent geospatial data either as
75+
a string containing a longitude-latitude pair (for example,
76+
"-104.991531, 39.742043") or as a JSON array of these
77+
strings. Note that the longitude value comes first in the
78+
string.
79+
80+
For example, you could index the `location` fields of the
81+
the [JSON]({{< relref "/develop/data-types/json" >}}) objects
82+
shown below as `GEO`:
83+
84+
```json
85+
{
86+
"description": "Navy Blue Slippers",
87+
"price": 45.99,
88+
"city": "Denver",
89+
"location": "-104.991531, 39.742043"
90+
}
91+
92+
{
93+
"description": "Bright Red Boots",
94+
"price": 185.75,
95+
"city": "Various",
96+
"location": [
97+
"-104.991531, 39.742043",
98+
"-105.0618814,40.5150098"
99+
]
100+
}
101+
```
102+
103+
`GEO` fields allow only basic point and radius queries.
104+
For example, the query below finds products within a 100 mile radius of Colorado Springs
105+
(Longitude=-104.800644, Latitude=38.846127).
106+
107+
```bash
108+
FT.SEARCH productidx '@location:[-104.800644 38.846127 100 mi]'
109+
```
110+
111+
See [Geospatial queries]({{< relref "/develop/interact/search-and-query/query/geo-spatial" >}})
112+
for more information about the available query options and see
113+
[Geospatial indexing]({{< relref "/develop/interact/search-and-query/indexing/geoindex" >}})
114+
for examples of indexing `GEO` fields.
115+
116+
## `GEOSHAPE`
117+
118+
Fields indexed as `GEOSHAPE` support the `POINT` and `POLYGON` primitives from the
119+
[Well-Known Text](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)
120+
representation of geometry. The `POINT` primitive defines a single point
121+
in a similar way to a `GEO` field.
122+
The `geom` field of the example JSON object shown below specifies a point
123+
(in Cartesian coordinates, using the standard x,y order):
124+
125+
```json
126+
{
127+
"name": "Purple Point",
128+
"geom": "POINT (2 2)"
129+
}
130+
```
131+
132+
The `POLYGON` primitive can approximate the outline of any shape using a
133+
sequence of points. Specify the coordinates of the corners in the order they
134+
occur around the shape (either clockwise or counter-clockwise) and ensure the
135+
shape is "closed" by making the final coordinate exactly the same as the first.
136+
137+
Note that `POLYGON` requires double parentheses around the coordinate list.
138+
This is because you can specify additional shapes as a comma-separated list
139+
that define "holes" within the enclosing polygon. The holes must have the opposite
140+
winding order to the outer polygon (so, if the outer polygon uses a clockwise winding
141+
order, the holes must use counter-clockwise).
142+
The `geom` field of the example JSON object shown below specifies a
143+
square using Cartesian coordinates in a clockwise winding order:
144+
145+
```json
146+
{
147+
"name": "Green Square",
148+
"geom": "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))"
149+
}
150+
```
151+
152+
The following examples define one `POINT` and three `POLYGON` primitives,
153+
which are shown in the image below:
154+
155+
```
156+
POINT (2 2)
157+
POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))
158+
POLYGON ((2 2.5, 2 3.5, 3.5 3.5, 3.5 2.5, 2 2.5))
159+
POLYGON ((3.5 1, 3.75 2, 4 1, 3.5 1))
160+
```
161+
162+
{{< image filename="/images/dev/rqe/geoshapes.jpg" >}}
41163

164+
You can run various types of query against a geospatial index. For
165+
example, the query below returns one primitive that lies within the boundary
166+
of the green square (from the example above) but omits the square itself:
42167

43-
## Specifying geospatial data in queries
168+
```bash
169+
> FT.SEARCH geomidx "(-@name:(Green Square) @geom:[WITHIN $qshape])" PARAMS 2 qshape "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))" RETURN 1 name DIALECT 4
44170

45-
Redis Query Engine uses the
46-
[*Well-Known Text* (WKT)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)
47-
format for geospatial data, specifically the `POINT` and `POLYGON`
48-
constructs. Add fields containing WKT data to your JSON objects,
49-
then add
171+
1) (integer) 1
172+
2) "shape:4"
173+
3) 1) "name"
174+
2) "[\"Purple Point\"]"
175+
```
50176

51-
### `POINT` data
177+
There are four query operations that you can use with `GEOSHAPE` fields:
52178

179+
- `WITHIN`: Find points or shapes that lie entirely within an
180+
enclosing shape that you specify in the query.
181+
- `CONTAINS`: Find shapes that completely contain the specified point
182+
or shape.
183+
- `INTERSECTS`: Find shapes whose boundary overlaps another specified
184+
shape.
185+
- `DISJOINT`: Find shapes whose boundary does not overlap another specified
186+
shape.
53187

188+
See
189+
[Geospatial queries]({{< relref "/develop/interact/search-and-query/query/geo-spatial" >}})
190+
for more information about these query types and see
191+
[Geospatial indexing]({{< relref "/develop/interact/search-and-query/indexing/geoindex" >}})
192+
for examples of indexing `GEOSHAPE` fields.

content/develop/interact/search-and-query/basic-constructs/field-and-type-options.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ You can also use the following query syntax to perform more complex numeric quer
6666

6767
Geo fields are used to store geographical coordinates such as longitude and latitude. They enable geospatial radius queries, which allow you to implement location-based search functionality in your applications such as finding nearby restaurants, stores, or any other points of interest.
6868

69+
Redis Query Engine also supports [geoshape fields](#geoshape-fields) for more advanced
70+
geospatial queries. See the
71+
[Geospatial]({{< relref "/develop/interact/search-and-query/advanced-concepts/geo" >}})
72+
reference page for an introduction to the format and usage of both schema types.
73+
6974
You can add geo fields to the schema in [`FT.CREATE`]({{< baseurl >}}/commands/ft.create/) using this syntax:
7075

7176
```
@@ -82,6 +87,57 @@ You can query geo fields using the `@<field_name>:[<lon> <lat> <radius> <unit>]`
8287
FT.SEARCH cities "@coords:[2.34 48.86 1000 km]"
8388
```
8489

90+
See
91+
[Geospatial queries]({{< relref "/develop/interact/search-and-query/query/geo-spatial" >}})
92+
for more information and code examples.
93+
94+
## Geoshape fields
95+
96+
Geoshape fields provide more advanced functionality than [Geo](#geo-fields).
97+
You can use them to represent locations as points but also to define
98+
shapes and query the interactions between points and shapes (for example,
99+
to find all points that are contained within an enclosing shape). You can
100+
also choose between geographical coordinates (on the surface of a sphere)
101+
or standard Cartesian coordinates. Use geoshape fields for spatial queries
102+
such as finding all office locations in a specified region or finding
103+
all rooms in a building that fall within range of a wi-fi router.
104+
105+
See the
106+
[Geospatial]({{< relref "/develop/interact/search-and-query/advanced-concepts/geo" >}})
107+
reference page for an introduction to the format and usage of both the
108+
geoshape and geo schema types.
109+
110+
Add geoshape fields to the schema in
111+
[`FT.CREATE`]({{< baseurl >}}/commands/ft.create/) using the following syntax:
112+
113+
```
114+
FT.CREATE ... SCHEMA ... {field_name} GEOSHAPE [FLAT|SPHERICAL] [NOINDEX]
115+
```
116+
117+
Where:
118+
- `FLAT` indicates Cartesian (planar) coordinates.
119+
- `SPHERICAL` indicates spherical (geographical) coordinates. This is the
120+
default option if you don't specify one explicitly.
121+
- `NOINDEX` indicates that the field is not indexed. This is useful for storing
122+
coordinates that you don't want to search for, but that you still want to retrieve
123+
in search results.
124+
125+
Note that unlike geo fields, geoshape fields don't support the `SORTABLE` option.
126+
127+
Query geoshape fields using the syntax `@<field_name>:[<OPERATION> <shape>]`
128+
where `<operation>` is one of `WITHIN`, `CONTAINS`, `INTERSECTS`, or `DISJOINT`,
129+
and `<shape>` is the shape of interest, specified in the
130+
[Well-known text](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)
131+
format. For example, the query below finds shapes that contain the point (2, 2):
132+
133+
```
134+
FT.SEARCH idx "(@geom:[CONTAINS $qshape])" PARAMS 2 qshape "POINT (2 2)" RETURN 1 name DIALECT 4
135+
```
136+
137+
See
138+
[Geospatial queries]({{< relref "/develop/interact/search-and-query/query/geo-spatial" >}})
139+
for more information and code examples.
140+
85141
## Vector fields
86142

87143
Vector fields are floating-point vectors that are typically generated by external machine learning models. These vectors represent unstructured data such as text, images, or other complex features. Redis Stack allows you to search for similar vectors using vector search algorithms like cosine similarity, Euclidean distance, and inner product. This enables you to build advanced search applications, recommendation systems, or content similarity analysis.

content/develop/interact/search-and-query/indexing/_index.md

Lines changed: 8 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -311,86 +311,14 @@ When JSONPath leads to multiple numerical values:
311311
- `null` values are skipped
312312
- Any other value type will cause an indexing failure
313313

314-
## Index JSON arrays as GEO
315-
316-
Starting with RediSearch v2.6.1, search can be done on an array of geo (geographical) values or on a JSONPath leading to multiple geo values.
317-
318-
Prior to RediSearch v2.6.1, only a single geo value was supported per GEO attribute. The geo value was specified using a comma delimited string in the form "longitude,latitude". For example, "15.447083,78.238306".
319-
320-
With RediSearch v2.6.1, a JSON array of such geo values is also supported.
321-
322-
In order to index multiple geo values, user either a JSONPath leading to a single array of geo values, or a JSONPath leading to multiple geo values, using JSONPath operators such as wildcard, filter, union, array slice, and/or recursive descent.
323-
324-
- `null` values are skipped
325-
- Other values will cause an indexing failure (bool, number, object, array, wrongly formatted GEO string, invalid coordinates)
326-
327-
For example, add to the item's list the `vendor_id`, that is, where an item can be physically purchased:
328-
329-
```sql
330-
127.0.0.1:6379> JSON.SET item:1 $ '{"name":"Noise-cancelling Bluetooth headphones","description":"Wireless Bluetooth headphones with noise-cancelling technology","connection":{"wireless":true,"type":"Bluetooth"},"price":99.98,"stock":25,"colors":["black","silver"], "max_level":[60, 70, 80, 90, 100], "vendor_id": [100,300]}'
331-
OK
332-
333-
127.0.0.1:6379> JSON.SET item:2 $ '{"name":"Wireless earbuds","description":"Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":64.99,"stock":17,"colors":["black","white"], "max_level":[80, 100, 120], "vendor_id": [100,200]}'
334-
OK
335-
336-
127.0.0.1:6379> JSON.SET item:3 $ '{"name":"True Wireless earbuds","description":"True Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":74.99,"stock":20,"colors":["red","light blue"], "max_level":[90, 100, 110, 120], "vendor_id": [100]}'
337-
OK
338-
```
339-
340-
Now add some vendors with their geographic locations:
341-
342-
```sql
343-
127.0.0.1:6379> JSON.SET vendor:1 $ '{"id":100, "name":"Kwik-E-Mart", "location":["35.213,31.785", "35.178,31.768", "35.827,31.984"]}'
344-
OK
345-
346-
127.0.0.1:6379> JSON.SET vendor:2 $ '{"id":200, "name":"Cypress Creek", "location":["34.638,31.79", "34.639,31.793"]}'
347-
OK
348-
349-
127.0.0.1:6379> JSON.SET vendor:3 $ '{"id":300, "name":"Barneys", "location":["34.648,31.817", "34.638,31.806", "34.65,31.785"]}'
350-
OK
351-
```
352-
353-
To index the `vendor_id` numeric array, specify the JSONPath `$.vendor_id` in the `SCHEMA` definition during index creation:
354-
355-
356-
```sql
357-
127.0.0.1:6379> FT.CREATE itemIdx5 ON JSON PREFIX 1 item: SCHEMA $.vendor_id AS vid NUMERIC
358-
OK
359-
```
360-
361-
To index the `location` geo array, specify the JSONPath `$.location` in the `SCHEMA` definition during index creation:
362-
363-
364-
```sql
365-
127.0.0.1:6379> FT.CREATE vendorIdx ON JSON PREFIX 1 vendor: SCHEMA $.location AS loc GEO
366-
OK
367-
```
368-
369-
Now search for a vendor close to a specific location. For example, a customer is located at geo coordinates 34.5,31.5 and you want to get the vendors that are within the range of 40 km from our location:
370-
371-
```sql
372-
127.0.0.1:6379> FT.SEARCH vendorIdx '@loc:[34.5 31.5 40 km]' return 1 $.id
373-
1) (integer) 2
374-
2) "vendor:2"
375-
3) 1) "$.id"
376-
1) "200"
377-
4) "vendor:3"
378-
5) 1) "$.id"
379-
1) "300"
380-
```
381-
382-
Now look for products offered by these vendors:
383-
384-
```
385-
127.0.0.1:6379> FT.SEARCH itemIdx5 '@vid:[200 300]'
386-
1) (integer) 2
387-
2) "item:2"
388-
3) 1) "$"
389-
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"max_level\":[80,100,120],\"vendor_id\":[100,200]}"
390-
4) "item:1"
391-
5) 1) "$"
392-
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"],\"max_level\":[60,70,80,90,100],\"vendor_id\":[100,300]}"
393-
```
314+
## Index JSON arrays as GEO and GEOSHAPE
315+
316+
You can use `GEO` and `GEOSHAPE` fields to store geospatial data,
317+
such as geographical locations and geometric shapes. See
318+
[Geospatial indexing]({{< relref "/develop/interact/search-and-query/indexing/geoindex" >}})
319+
to learn how to use these schema types and see the
320+
[Geospatial]({{< relref "/develop/interact/search-and-query/advanced-concepts/geo" >}})
321+
reference page for an introduction to their format and usage.
394322

395323
## Index JSON arrays as VECTOR
396324

0 commit comments

Comments
 (0)