fred/commands/interfaces/
geo.rs

1use crate::{
2  commands,
3  error::Error,
4  interfaces::{ClientLike, FredResult},
5  types::{
6    geo::{GeoPosition, GeoUnit, MultipleGeoValues},
7    Any,
8    FromValue,
9    Key,
10    MultipleValues,
11    SetOptions,
12    SortOrder,
13    Value,
14  },
15};
16use fred_macros::rm_send_if;
17use futures::Future;
18use std::convert::TryInto;
19
20/// Functions that implement the [geo](https://redis.io/commands#geo) interface.
21#[rm_send_if(feature = "glommio")]
22pub trait GeoInterface: ClientLike + Sized {
23  /// Adds the specified geospatial items (longitude, latitude, name) to the specified key.
24  ///
25  /// <https://redis.io/commands/geoadd>
26  fn geoadd<R, K, V>(
27    &self,
28    key: K,
29    options: Option<SetOptions>,
30    changed: bool,
31    values: V,
32  ) -> impl Future<Output = FredResult<R>> + Send
33  where
34    R: FromValue,
35    K: Into<Key> + Send,
36    V: Into<MultipleGeoValues> + Send,
37  {
38    async move {
39      into!(key, values);
40      commands::geo::geoadd(self, key, options, changed, values)
41        .await?
42        .convert()
43    }
44  }
45
46  /// Return valid Geohash strings representing the position of one or more elements in a sorted set value
47  /// representing a geospatial index (where elements were added using GEOADD).
48  ///
49  /// <https://redis.io/commands/geohash>
50  fn geohash<R, K, V>(&self, key: K, members: V) -> impl Future<Output = FredResult<R>> + Send
51  where
52    R: FromValue,
53    K: Into<Key> + Send,
54    V: TryInto<MultipleValues> + Send,
55    V::Error: Into<Error> + Send,
56  {
57    async move {
58      into!(key);
59      try_into!(members);
60      commands::geo::geohash(self, key, members).await?.convert()
61    }
62  }
63
64  /// Return the positions (longitude,latitude) of all the specified members of the geospatial index represented by
65  /// the sorted set at key.
66  ///
67  /// Callers can use [as_geo_position](crate::types::Value::as_geo_position) to lazily parse results as needed.
68  ///
69  /// <https://redis.io/commands/geopos>
70  fn geopos<R, K, V>(&self, key: K, members: V) -> impl Future<Output = FredResult<R>> + Send
71  where
72    R: FromValue,
73    K: Into<Key> + Send,
74    V: TryInto<MultipleValues> + Send,
75    V::Error: Into<Error> + Send,
76  {
77    async move {
78      into!(key);
79      try_into!(members);
80      commands::geo::geopos(self, key, members).await?.convert()
81    }
82  }
83
84  /// Return the distance between two members in the geospatial index represented by the sorted set.
85  ///
86  /// <https://redis.io/commands/geodist>
87  fn geodist<R, K, S, D>(
88    &self,
89    key: K,
90    src: S,
91    dest: D,
92    unit: Option<GeoUnit>,
93  ) -> impl Future<Output = FredResult<R>> + Send
94  where
95    R: FromValue,
96    K: Into<Key> + Send,
97    S: TryInto<Value> + Send,
98    S::Error: Into<Error> + Send,
99    D: TryInto<Value> + Send,
100    D::Error: Into<Error> + Send,
101  {
102    async move {
103      into!(key);
104      try_into!(src, dest);
105      commands::geo::geodist(self, key, src, dest, unit).await?.convert()
106    }
107  }
108
109  /// Return the members of a sorted set populated with geospatial information using GEOADD, which are within the
110  /// borders of the area specified with the center location and the maximum distance from the center (the radius).
111  ///
112  /// <https://redis.io/commands/georadius>
113  fn georadius<R, K, P>(
114    &self,
115    key: K,
116    position: P,
117    radius: f64,
118    unit: GeoUnit,
119    withcoord: bool,
120    withdist: bool,
121    withhash: bool,
122    count: Option<(u64, Any)>,
123    ord: Option<SortOrder>,
124    store: Option<Key>,
125    storedist: Option<Key>,
126  ) -> impl Future<Output = FredResult<R>> + Send
127  where
128    R: FromValue,
129    K: Into<Key> + Send,
130    P: Into<GeoPosition> + Send,
131  {
132    async move {
133      into!(key, position);
134      commands::geo::georadius(
135        self, key, position, radius, unit, withcoord, withdist, withhash, count, ord, store, storedist,
136      )
137      .await?
138      .convert()
139    }
140  }
141
142  /// This command is exactly like GEORADIUS with the sole difference that instead of taking, as the center of the
143  /// area to query, a longitude and latitude value, it takes the name of a member already existing inside the
144  /// geospatial index represented by the sorted set.
145  ///
146  /// <https://redis.io/commands/georadiusbymember>
147  fn georadiusbymember<R, K, V>(
148    &self,
149    key: K,
150    member: V,
151    radius: f64,
152    unit: GeoUnit,
153    withcoord: bool,
154    withdist: bool,
155    withhash: bool,
156    count: Option<(u64, Any)>,
157    ord: Option<SortOrder>,
158    store: Option<Key>,
159    storedist: Option<Key>,
160  ) -> impl Future<Output = FredResult<R>> + Send
161  where
162    R: FromValue,
163    K: Into<Key> + Send,
164    V: TryInto<Value> + Send,
165    V::Error: Into<Error> + Send,
166  {
167    async move {
168      into!(key);
169      try_into!(member);
170      commands::geo::georadiusbymember(
171        self,
172        key,
173        to!(member)?,
174        radius,
175        unit,
176        withcoord,
177        withdist,
178        withhash,
179        count,
180        ord,
181        store,
182        storedist,
183      )
184      .await?
185      .convert()
186    }
187  }
188
189  /// Return the members of a sorted set populated with geospatial information using GEOADD, which are within the
190  /// borders of the area specified by a given shape.
191  ///
192  /// <https://redis.io/commands/geosearch>
193  fn geosearch<R, K>(
194    &self,
195    key: K,
196    from_member: Option<Value>,
197    from_lonlat: Option<GeoPosition>,
198    by_radius: Option<(f64, GeoUnit)>,
199    by_box: Option<(f64, f64, GeoUnit)>,
200    ord: Option<SortOrder>,
201    count: Option<(u64, Any)>,
202    withcoord: bool,
203    withdist: bool,
204    withhash: bool,
205  ) -> impl Future<Output = FredResult<R>> + Send
206  where
207    R: FromValue,
208    K: Into<Key> + Send,
209  {
210    async move {
211      into!(key);
212      commands::geo::geosearch(
213        self,
214        key,
215        from_member,
216        from_lonlat,
217        by_radius,
218        by_box,
219        ord,
220        count,
221        withcoord,
222        withdist,
223        withhash,
224      )
225      .await?
226      .convert()
227    }
228  }
229
230  /// This command is like GEOSEARCH, but stores the result in destination key. Returns the number of members added to
231  /// the destination key.
232  ///
233  /// <https://redis.io/commands/geosearchstore>
234  fn geosearchstore<R, D, S>(
235    &self,
236    dest: D,
237    source: S,
238    from_member: Option<Value>,
239    from_lonlat: Option<GeoPosition>,
240    by_radius: Option<(f64, GeoUnit)>,
241    by_box: Option<(f64, f64, GeoUnit)>,
242    ord: Option<SortOrder>,
243    count: Option<(u64, Any)>,
244    storedist: bool,
245  ) -> impl Future<Output = FredResult<R>> + Send
246  where
247    R: FromValue,
248    D: Into<Key> + Send,
249    S: Into<Key> + Send,
250  {
251    async move {
252      into!(dest, source);
253      commands::geo::geosearchstore(
254        self,
255        dest,
256        source,
257        from_member,
258        from_lonlat,
259        by_radius,
260        by_box,
261        ord,
262        count,
263        storedist,
264      )
265      .await?
266      .convert()
267    }
268  }
269}