diff options
-rw-r--r-- | redis/commands.py | 26 | ||||
-rw-r--r-- | tests/test_commands.py | 80 |
2 files changed, 77 insertions, 29 deletions
diff --git a/redis/commands.py b/redis/commands.py index 9bd57e8..9dad8a5 100644 --- a/redis/commands.py +++ b/redis/commands.py @@ -2904,17 +2904,39 @@ class Commands: return Script(self, script) # GEO COMMANDS - def geoadd(self, name, *values): + def geoadd(self, name, values, nx=False, xx=False, ch=False): """ Add the specified geospatial items to the specified key identified by the ``name`` argument. The Geospatial items are given as ordered members of the ``values`` argument, each item or place is formed by the triad longitude, latitude and name. + + Note: You can use ZREM to remove elements. + + ``nx`` forces ZADD to only create new elements and not to update + scores for elements that already exist. + + ``xx`` forces ZADD to only update scores of elements that already + exist. New elements will not be added. + + ``ch`` modifies the return value to be the numbers of elements changed. + Changed elements include new elements that were added and elements + whose scores changed. """ + if nx and xx: + raise DataError("GEOADD allows either 'nx' or 'xx', not both") if len(values) % 3 != 0: raise DataError("GEOADD requires places with lon, lat and name" " values") - return self.execute_command('GEOADD', name, *values) + pieces = [name] + if nx: + pieces.append('NX') + if xx: + pieces.append('XX') + if ch: + pieces.append('CH') + pieces.extend(values) + return self.execute_command('GEOADD', *pieces) def geodist(self, name, place1, place2, unit=None): """ diff --git a/tests/test_commands.py b/tests/test_commands.py index 8929198..802d8e4 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -2422,35 +2422,63 @@ class TestRedisCommands: def test_geoadd(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - - assert r.geoadd('barcelona', *values) == 2 + assert r.geoadd('barcelona', values) == 2 assert r.zcard('barcelona') == 2 + @skip_if_server_version_lt('6.2.0') + def test_geoadd_nx(self, r): + values = (2.1909389952632, 41.433791470673, 'place1') + \ + (2.1873744593677, 41.406342043777, 'place2') + assert r.geoadd('a', values) == 2 + values = (2.1909389952632, 41.433791470673, 'place1') + \ + (2.1873744593677, 41.406342043777, 'place2') + \ + (2.1804738294738, 41.405647879212, 'place3') + assert r.geoadd('a', values, nx=True) == 1 + assert r.zrange('a', 0, -1) == [b'place3', b'place2', b'place1'] + + @skip_if_server_version_lt('6.2.0') + def test_geoadd_xx(self, r): + values = (2.1909389952632, 41.433791470673, 'place1') + assert r.geoadd('a', values) == 1 + values = (2.1909389952632, 41.433791470673, 'place1') + \ + (2.1873744593677, 41.406342043777, 'place2') + assert r.geoadd('a', values, xx=True) == 0 + assert r.zrange('a', 0, -1) == \ + [b'place1'] + + @skip_if_server_version_lt('6.2.0') + def test_geoadd_ch(self, r): + values = (2.1909389952632, 41.433791470673, 'place1') + assert r.geoadd('a', values) == 1 + values = (2.1909389952632, 31.433791470673, 'place1') + \ + (2.1873744593677, 41.406342043777, 'place2') + assert r.geoadd('a', values, ch=True) == 2 + assert r.zrange('a', 0, -1) == \ + [b'place1', b'place2'] + @skip_if_server_version_lt('3.2.0') def test_geoadd_invalid_params(self, r): with pytest.raises(exceptions.RedisError): - r.geoadd('barcelona', *(1, 2)) + r.geoadd('barcelona', (1, 2)) @skip_if_server_version_lt('3.2.0') def test_geodist(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - - assert r.geoadd('barcelona', *values) == 2 + assert r.geoadd('barcelona', values) == 2 assert r.geodist('barcelona', 'place1', 'place2') == 3067.4157 @skip_if_server_version_lt('3.2.0') def test_geodist_units(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.geodist('barcelona', 'place1', 'place2', 'km') == 3.0674 @skip_if_server_version_lt('3.2.0') def test_geodist_missing_one_member(self, r): values = (2.1909389952632, 41.433791470673, 'place1') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.geodist('barcelona', 'place1', 'missing_member', 'km') is None @skip_if_server_version_lt('3.2.0') @@ -2462,8 +2490,7 @@ class TestRedisCommands: def test_geohash(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.geohash('barcelona', 'place1', 'place2', 'place3') == \ ['sp3e9yg3kd0', 'sp3e9cbc3t0', None] @@ -2472,8 +2499,7 @@ class TestRedisCommands: def test_geopos(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) # redis uses 52 bits precision, hereby small errors may be introduced. assert r.geopos('barcelona', 'place1', 'place2') == \ [(2.19093829393386841, 41.43379028184083523), @@ -2493,7 +2519,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, b'\x80place2') + \ (2.583333, 41.316667, 'place3') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.geosearch('barcelona', longitude=2.191, latitude=41.433, radius=1000) == [b'place1'] assert r.geosearch('barcelona', longitude=2.187, @@ -2515,7 +2541,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, b'\x80place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.geosearch('barcelona', member='place1', radius=4000) == \ [b'\x80place2', b'place1'] assert r.geosearch('barcelona', member='place1', radius=10) == \ @@ -2534,7 +2560,7 @@ class TestRedisCommands: def test_geosearch_sort(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.geosearch('barcelona', longitude=2.191, latitude=41.433, radius=3000, sort='ASC') == \ [b'place1', b'place2'] @@ -2547,7 +2573,7 @@ class TestRedisCommands: def test_geosearch_with(self, r): values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) # test a bunch of combinations to test the parse response # function. @@ -2618,7 +2644,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) r.geosearchstore('places_barcelona', 'barcelona', longitude=2.191, latitude=41.433, radius=1000) assert r.zrange('places_barcelona', 0, -1) == [b'place1'] @@ -2629,7 +2655,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) r.geosearchstore('places_barcelona', 'barcelona', longitude=2.191, latitude=41.433, radius=1000, storedist=True) @@ -2641,7 +2667,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, b'\x80place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.georadius('barcelona', 2.191, 41.433, 1000) == [b'place1'] assert r.georadius('barcelona', 2.187, 41.406, 1000) == [b'\x80place2'] @@ -2650,7 +2676,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.georadius('barcelona', 1, 2, 1000) == [] @skip_if_server_version_lt('3.2.0') @@ -2658,7 +2684,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.georadius('barcelona', 2.191, 41.433, 1, unit='km') == \ [b'place1'] @@ -2668,7 +2694,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) # test a bunch of combinations to test the parse response # function. @@ -2696,7 +2722,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.georadius('barcelona', 2.191, 41.433, 3000, count=1) == \ [b'place1'] assert r.georadius('barcelona', 2.191, 41.433, 3000, @@ -2708,7 +2734,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.georadius('barcelona', 2.191, 41.433, 3000, sort='ASC') == \ [b'place1', b'place2'] assert r.georadius('barcelona', 2.191, 41.433, 3000, sort='DESC') == \ @@ -2719,7 +2745,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) r.georadius('barcelona', 2.191, 41.433, 1000, store='places_barcelona') assert r.zrange('places_barcelona', 0, -1) == [b'place1'] @@ -2729,7 +2755,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, 'place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) r.georadius('barcelona', 2.191, 41.433, 1000, store_dist='places_barcelona') # instead of save the geo score, the distance is saved. @@ -2741,7 +2767,7 @@ class TestRedisCommands: values = (2.1909389952632, 41.433791470673, 'place1') + \ (2.1873744593677, 41.406342043777, b'\x80place2') - r.geoadd('barcelona', *values) + r.geoadd('barcelona', values) assert r.georadiusbymember('barcelona', 'place1', 4000) == \ [b'\x80place2', b'place1'] assert r.georadiusbymember('barcelona', 'place1', 10) == [b'place1'] |