From 6852bd390e02513cfeb666a3aab67b091b42e620 Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Mon, 25 Jan 2021 12:14:34 +0300 Subject: [PATCH] Feature - add tryAdd() method to RGeo object #3381 --- .../main/java/org/redisson/RedissonGeo.java | 41 +++++++++++++++---- .../src/main/java/org/redisson/api/RGeo.java | 24 ++++++++++- .../main/java/org/redisson/api/RGeoAsync.java | 24 ++++++++++- .../java/org/redisson/api/RGeoReactive.java | 23 +++++++++++ .../main/java/org/redisson/api/RGeoRx.java | 22 ++++++++++ .../client/protocol/RedisCommands.java | 1 + .../java/org/redisson/RedissonGeoTest.java | 22 ++++++++++ 7 files changed, 147 insertions(+), 10 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonGeo.java b/redisson/src/main/java/org/redisson/RedissonGeo.java index dfb2fc37b..5d973f217 100644 --- a/redisson/src/main/java/org/redisson/RedissonGeo.java +++ b/redisson/src/main/java/org/redisson/RedissonGeo.java @@ -16,10 +16,7 @@ package org.redisson; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import org.redisson.api.GeoEntry; import org.redisson.api.GeoOrder; @@ -118,7 +115,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo extends RedissonScoredSortedSet implements RGeo addIfExistsAsync(double longitude, double latitude, V member) { - return commandExecutor.writeAsync(getName(), codec, RedisCommands.GEOADD, getName(), "XX", convert(longitude), - convert(latitude), encode(member)); + public RFuture addIfExistsAsync(double longitude, double latitude, V member) { + return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN, + "local value = redis.call('geopos', KEYS[1], ARGV[3]); " + + "if value[1] ~= false then " + + "redis.call('geoadd', KEYS[1], ARGV[1], ARGV[2], ARGV[3]); " + + "return 1; " + + "end; " + + "return 0; ", + Collections.singletonList(getName()), + convert(longitude), convert(latitude), encode(member)); } @Override @@ -138,6 +142,27 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo tryAddAsync(double longitude, double latitude, V member) { + return commandExecutor.writeAsync(getName(), codec, RedisCommands.GEOADD_BOOLEAN, getName(), "NX", convert(longitude), + convert(latitude), encode(member)); + } + + @Override + public RFuture tryAddAsync(GeoEntry... entries) { + return addAsync("NX", entries); + } + @Override public Double dist(V firstMember, V secondMember, GeoUnit geoUnit) { return get(distAsync(firstMember, secondMember, geoUnit)); diff --git a/redisson/src/main/java/org/redisson/api/RGeo.java b/redisson/src/main/java/org/redisson/api/RGeo.java index 875a62202..3c7a9a39e 100644 --- a/redisson/src/main/java/org/redisson/api/RGeo.java +++ b/redisson/src/main/java/org/redisson/api/RGeo.java @@ -59,7 +59,7 @@ public interface RGeo extends RScoredSortedSet, RGeoAsync { * @param member - object itself * @return number of elements added to the sorted set */ - long addIfExists(double longitude, double latitude, V member); + Boolean addIfExists(double longitude, double latitude, V member); /** * Adds geospatial members only if it's already exists. @@ -71,6 +71,28 @@ public interface RGeo extends RScoredSortedSet, RGeoAsync { */ long addIfExists(GeoEntry... entries); + /** + * Adds geospatial member only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param longitude - longitude of object + * @param latitude - latitude of object + * @param member - object itself + * @return number of elements added to the sorted set + */ + boolean tryAdd(double longitude, double latitude, V member); + + /** + * Adds geospatial members only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param entries - objects + * @return number of elements added to the sorted set + */ + long tryAdd(GeoEntry... entries); + /** * Returns distance between members in GeoUnit units. * diff --git a/redisson/src/main/java/org/redisson/api/RGeoAsync.java b/redisson/src/main/java/org/redisson/api/RGeoAsync.java index ea97b159f..e553606a1 100644 --- a/redisson/src/main/java/org/redisson/api/RGeoAsync.java +++ b/redisson/src/main/java/org/redisson/api/RGeoAsync.java @@ -59,7 +59,7 @@ public interface RGeoAsync extends RScoredSortedSetAsync { * @param member - object itself * @return number of elements added to the sorted set */ - RFuture addIfExistsAsync(double longitude, double latitude, V member); + RFuture addIfExistsAsync(double longitude, double latitude, V member); /** * Adds geospatial members only if it's already exists. @@ -71,6 +71,28 @@ public interface RGeoAsync extends RScoredSortedSetAsync { */ RFuture addIfExistsAsync(GeoEntry... entries); + /** + * Adds geospatial member only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param longitude - longitude of object + * @param latitude - latitude of object + * @param member - object itself + * @return number of elements added to the sorted set + */ + RFuture tryAddAsync(double longitude, double latitude, V member); + + /** + * Adds geospatial members only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param entries - objects + * @return number of elements added to the sorted set + */ + RFuture tryAddAsync(GeoEntry... entries); + /** * Returns distance between members in GeoUnit units. * diff --git a/redisson/src/main/java/org/redisson/api/RGeoReactive.java b/redisson/src/main/java/org/redisson/api/RGeoReactive.java index 6797f5d02..295830fb5 100644 --- a/redisson/src/main/java/org/redisson/api/RGeoReactive.java +++ b/redisson/src/main/java/org/redisson/api/RGeoReactive.java @@ -18,6 +18,7 @@ package org.redisson.api; import java.util.List; import java.util.Map; +import io.reactivex.rxjava3.core.Single; import reactor.core.publisher.Mono; /** @@ -73,6 +74,28 @@ public interface RGeoReactive extends RScoredSortedSetReactive { */ Mono addIfExists(GeoEntry... entries); + /** + * Adds geospatial member only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param longitude - longitude of object + * @param latitude - latitude of object + * @param member - object itself + * @return number of elements added to the sorted set + */ + Mono tryAdd(double longitude, double latitude, V member); + + /** + * Adds geospatial members only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param entries - objects + * @return number of elements added to the sorted set + */ + Mono tryAdd(GeoEntry... entries); + /** * Returns distance between members in GeoUnit units. * diff --git a/redisson/src/main/java/org/redisson/api/RGeoRx.java b/redisson/src/main/java/org/redisson/api/RGeoRx.java index 928caadab..cbb0571e4 100644 --- a/redisson/src/main/java/org/redisson/api/RGeoRx.java +++ b/redisson/src/main/java/org/redisson/api/RGeoRx.java @@ -73,6 +73,28 @@ public interface RGeoRx extends RScoredSortedSetRx { */ Single addIfExists(GeoEntry... entries); + /** + * Adds geospatial member only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param longitude - longitude of object + * @param latitude - latitude of object + * @param member - object itself + * @return number of elements added to the sorted set + */ + Single tryAdd(double longitude, double latitude, V member); + + /** + * Adds geospatial members only if has not been added before. + *

+ * Requires Redis 6.2.0 and higher. + * + * @param entries - objects + * @return number of elements added to the sorted set + */ + Single tryAdd(GeoEntry... entries); + /** * Returns distance between members in GeoUnit units. * diff --git a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java index 5b7432613..ae69efe1c 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -62,6 +62,7 @@ public interface RedisCommands { RedisStrictCommand DEBUG = new RedisStrictCommand("DEBUG"); RedisStrictCommand GEOADD = new RedisStrictCommand("GEOADD"); + RedisStrictCommand GEOADD_BOOLEAN = new RedisStrictCommand<>("GEOADD", new BooleanReplayConvertor()); RedisCommand GEODIST = new RedisCommand("GEODIST", new DoubleReplayConvertor()); RedisCommand> GEORADIUS_RO = new RedisCommand>("GEORADIUS_RO", new ObjectListReplayDecoder()); RedisCommand> GEORADIUSBYMEMBER_RO = new RedisCommand>("GEORADIUSBYMEMBER_RO", new ObjectListReplayDecoder()); diff --git a/redisson/src/test/java/org/redisson/RedissonGeoTest.java b/redisson/src/test/java/org/redisson/RedissonGeoTest.java index 43cc15c44..355f0f528 100644 --- a/redisson/src/test/java/org/redisson/RedissonGeoTest.java +++ b/redisson/src/test/java/org/redisson/RedissonGeoTest.java @@ -36,6 +36,28 @@ public class RedissonGeoTest extends BaseTest { assertThat(geo.add(2.51, 3.12, "city1")).isEqualTo(1); } + @Test + public void testAddIfExists() { + RGeo geo = redisson.getGeo("test"); + + assertThat(geo.add(2.51, 3.12, "city1")).isEqualTo(1); + assertThat(geo.addIfExists(2.9, 3.9, "city1")).isTrue(); + Map pos = geo.pos("city1"); + System.out.println("" + pos.get("city1")); + assertThat(pos.get("city1").getLatitude()).isBetween(3.8, 3.9); + assertThat(pos.get("city1").getLongitude()).isBetween(2.8, 3.0); + + assertThat(geo.addIfExists(2.12, 3.5, "city2")).isFalse(); + } + + @Test + public void testTryAdd() { + RGeo geo = redisson.getGeo("test"); + assertThat(geo.add(2.51, 3.12, "city1")).isEqualTo(1); + assertThat(geo.tryAdd(2.5, 3.1, "city1")).isFalse(); + assertThat(geo.tryAdd(2.12, 3.5, "city2")).isTrue(); + } + @Test public void testAddEntries() { RGeo geo = redisson.getGeo("test");