package com.lambdaworks.redis.commands; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.offset; import java.util.List; import java.util.Set; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import com.lambdaworks.redis.*; public class GeoCommandTest extends AbstractRedisClientTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void geoadd() throws Exception { Long result = redis.geoadd(key, -73.9454966, 40.747533, "lic market"); assertThat(result).isEqualTo(1); Long readd = redis.geoadd(key, -73.9454966, 40.747533, "lic market"); assertThat(readd).isEqualTo(0); } @Test public void geoaddWithTransaction() throws Exception { redis.multi(); redis.geoadd(key, -73.9454966, 40.747533, "lic market"); redis.geoadd(key, -73.9454966, 40.747533, "lic market"); assertThat(redis.exec()).containsSequence(1L, 0L); } @Test public void geoaddMulti() throws Exception { Long result = redis.geoadd(key, 8.6638775, 49.5282537, "Weinheim", 8.3796281, 48.9978127, "EFS9", 8.665351, 49.553302, "Bahn"); assertThat(result).isEqualTo(3); } @Test public void geoaddMultiWithTransaction() throws Exception { redis.multi(); redis.geoadd(key, 8.6638775, 49.5282537, "Weinheim", 8.3796281, 48.9978127, "EFS9", 8.665351, 49.553302, "Bahn"); assertThat(redis.exec()).contains(3L); } @Test(expected = IllegalArgumentException.class) public void geoaddMultiWrongArgument() throws Exception { redis.geoadd(key, 49.528253); } protected void prepareGeo() { redis.geoadd(key, 8.6638775, 49.5282537, "Weinheim"); redis.geoadd(key, 8.3796281, 48.9978127, "EFS9", 8.665351, 49.553302, "Bahn"); } @Test public void georadius() throws Exception { prepareGeo(); Set<String> georadius = redis.georadius(key, 8.6582861, 49.5285695, 1, GeoArgs.Unit.km); assertThat(georadius).hasSize(1).contains("Weinheim"); Set<String> largerGeoradius = redis.georadius(key, 8.6582861, 49.5285695, 5, GeoArgs.Unit.km); assertThat(largerGeoradius).hasSize(2).contains("Weinheim").contains("Bahn"); } @Test public void georadiusWithTransaction() throws Exception { prepareGeo(); redis.multi(); redis.georadius(key, 8.6582861, 49.5285695, 1, GeoArgs.Unit.km); redis.georadius(key, 8.6582861, 49.5285695, 5, GeoArgs.Unit.km); List<Object> exec = redis.exec(); Set<String> georadius = (Set<String>) exec.get(0); Set<String> largerGeoradius = (Set<String>) exec.get(1); assertThat(georadius).hasSize(1).contains("Weinheim"); assertThat(largerGeoradius).hasSize(2).contains("Weinheim").contains("Bahn"); } @Test public void geodist() throws Exception { prepareGeo(); Double result = redis.geodist(key, "Weinheim", "Bahn", GeoArgs.Unit.km); // 10 mins with the bike assertThat(result).isGreaterThan(2.5).isLessThan(2.9); } // See https://github.com/antirez/redis/issues/3512 and https://github.com/mp911de/lettuce/issues/362 @Test(expected = RedisException.class) public void geodistMissingElements() throws Exception { prepareGeo(); assertThat(redis.geodist("Unknown", "Unknown", "Bahn", GeoArgs.Unit.km)).isNull(); assertThat(redis.geodist(key, "Unknown", "Bahn", GeoArgs.Unit.km)).isNull(); assertThat(redis.geodist(key, "Weinheim", "Unknown", GeoArgs.Unit.km)).isNull(); } @Test public void geodistWithTransaction() throws Exception { prepareGeo(); redis.multi(); redis.geodist(key, "Weinheim", "Bahn", GeoArgs.Unit.km); Double result = (Double) redis.exec().get(0); // 10 mins with the bike assertThat(result).isGreaterThan(2.5).isLessThan(2.9); } @Test public void geopos() throws Exception { prepareGeo(); List<GeoCoordinates> geopos = redis.geopos(key, "Weinheim", "foobar", "Bahn"); assertThat(geopos).hasSize(3); assertThat(geopos.get(0).getX().doubleValue()).isEqualTo(8.6638, offset(0.001)); assertThat(geopos.get(1)).isNull(); assertThat(geopos.get(2)).isNotNull(); } @Test public void geoposWithTransaction() throws Exception { prepareGeo(); redis.multi(); redis.geopos(key, "Weinheim", "foobar", "Bahn"); redis.geopos(key, "Weinheim", "foobar", "Bahn"); List<GeoCoordinates> geopos = (List) redis.exec().get(1); assertThat(geopos).hasSize(3); assertThat(geopos.get(0).getX().doubleValue()).isEqualTo(8.6638, offset(0.001)); assertThat(geopos.get(1)).isNull(); assertThat(geopos.get(2)).isNotNull(); } @Test public void georadiusWithArgs() throws Exception { prepareGeo(); GeoArgs geoArgs = new GeoArgs().withHash().withCoordinates().withDistance().withCount(1).desc(); List<GeoWithin<String>> result = redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, geoArgs); assertThat(result).hasSize(1); GeoWithin<String> weinheim = result.get(0); assertThat(weinheim.getMember()).isEqualTo("Weinheim"); assertThat(weinheim.getGeohash()).isEqualTo(3666615932941099L); assertThat(weinheim.getDistance()).isEqualTo(2.7882, offset(0.5)); assertThat(weinheim.getCoordinates().getX().doubleValue()).isEqualTo(8.663875, offset(0.5)); assertThat(weinheim.getCoordinates().getY().doubleValue()).isEqualTo(49.52825, offset(0.5)); result = redis.georadius(key, 8.665351, 49.553302, 1, GeoArgs.Unit.km, new GeoArgs()); assertThat(result).hasSize(1); GeoWithin<String> bahn = result.get(0); assertThat(bahn.getMember()).isEqualTo("Bahn"); assertThat(bahn.getGeohash()).isNull(); assertThat(bahn.getDistance()).isNull(); assertThat(bahn.getCoordinates()).isNull(); } @Test public void georadiusWithArgsAndTransaction() throws Exception { prepareGeo(); redis.multi(); GeoArgs geoArgs = new GeoArgs().withHash().withCoordinates().withDistance().withCount(1).desc(); redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, geoArgs); redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, geoArgs); List<Object> exec = redis.exec(); assertThat(exec).hasSize(2); List<GeoWithin<String>> result = (List) exec.get(1); assertThat(result).hasSize(1); GeoWithin<String> weinheim = result.get(0); assertThat(weinheim.getMember()).isEqualTo("Weinheim"); assertThat(weinheim.getGeohash()).isEqualTo(3666615932941099L); assertThat(weinheim.getDistance()).isEqualTo(2.7882, offset(0.5)); assertThat(weinheim.getCoordinates().getX().doubleValue()).isEqualTo(8.663875, offset(0.5)); assertThat(weinheim.getCoordinates().getY().doubleValue()).isEqualTo(49.52825, offset(0.5)); result = redis.georadius(key, 8.665351, 49.553302, 1, GeoArgs.Unit.km, new GeoArgs()); assertThat(result).hasSize(1); GeoWithin<String> bahn = result.get(0); assertThat(bahn.getMember()).isEqualTo("Bahn"); assertThat(bahn.getGeohash()).isNull(); assertThat(bahn.getDistance()).isNull(); assertThat(bahn.getCoordinates()).isNull(); } @Test public void geohash() throws Exception { prepareGeo(); List<String> geohash = redis.geohash(key, "Weinheim", "Bahn", "dunno"); assertThat(geohash).containsSequence("u0y1v0kffz0", "u0y1vhvuvm0", null); } @Test public void geohashUnknownKey() throws Exception { prepareGeo(); List<String> geohash = redis.geohash("dunno", "member"); assertThat(geohash).isEmpty(); } @Test public void geohashWithTransaction() throws Exception { prepareGeo(); redis.multi(); redis.geohash(key, "Weinheim", "Bahn", "dunno"); redis.geohash(key, "Weinheim", "Bahn", "dunno"); List<Object> exec = redis.exec(); List<String> geohash = (List) exec.get(1); assertThat(geohash).containsSequence("u0y1v0kffz0", "u0y1vhvuvm0", null); } @Test public void georadiusStore() throws Exception { prepareGeo(); String resultKey = "38o54"; // yields in same slot as "key" Long result = redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, new GeoRadiusStoreArgs<>().withStore(resultKey)); assertThat(result).isEqualTo(2); List<ScoredValue<String>> results = redis.zrangeWithScores(resultKey, 0, -1); assertThat(results).hasSize(2); } @Test public void georadiusStoreWithCountAndSort() throws Exception { prepareGeo(); String resultKey = "38o54"; // yields in same slot as "key" Long result = redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, new GeoRadiusStoreArgs<>().withCount(1).desc().withStore(resultKey)); assertThat(result).isEqualTo(1); List<ScoredValue<String>> results = redis.zrangeWithScores(resultKey, 0, -1); assertThat(results).hasSize(1); assertThat(results.get(0).score).isGreaterThan(99999); } @Test public void georadiusStoreDist() throws Exception { prepareGeo(); String resultKey = "38o54"; // yields in same slot as "key" Long result = redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, new GeoRadiusStoreArgs<>().withStoreDist("38o54")); assertThat(result).isEqualTo(2); List<ScoredValue<String>> dist = redis.zrangeWithScores(resultKey, 0, -1); assertThat(dist).hasSize(2); } @Test public void georadiusStoreDistWithCountAndSort() throws Exception { prepareGeo(); String resultKey = "38o54"; // yields in same slot as "key" Long result = redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, new GeoRadiusStoreArgs<>().withCount(1).desc().withStoreDist("38o54")); assertThat(result).isEqualTo(1); List<ScoredValue<String>> dist = redis.zrangeWithScores(resultKey, 0, -1); assertThat(dist).hasSize(1); assertThat(dist.get(0).score).isBetween(2d, 3d); } @Test(expected = IllegalArgumentException.class) public void georadiusWithNullArgs() throws Exception { redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, (GeoArgs) null); } @Test(expected = IllegalArgumentException.class) public void georadiusStoreWithNullArgs() throws Exception { redis.georadius(key, 8.665351, 49.553302, 5, GeoArgs.Unit.km, (GeoRadiusStoreArgs<String>) null); } @Test public void georadiusbymember() throws Exception { prepareGeo(); Set<String> empty = redis.georadiusbymember(key, "Bahn", 1, GeoArgs.Unit.km); assertThat(empty).hasSize(1).contains("Bahn"); Set<String> georadiusbymember = redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km); assertThat(georadiusbymember).hasSize(2).contains("Bahn", "Weinheim"); } @Test public void georadiusbymemberStoreDistWithCountAndSort() throws Exception { prepareGeo(); String resultKey = "38o54"; // yields in same slot as "key" Long result = redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoRadiusStoreArgs<>().withCount(1).desc().withStoreDist("38o54")); assertThat(result).isEqualTo(1); List<ScoredValue<String>> dist = redis.zrangeWithScores(resultKey, 0, -1); assertThat(dist).hasSize(1); assertThat(dist.get(0).score).isBetween(2d, 3d); } @Test public void georadiusbymemberWithArgs() throws Exception { prepareGeo(); List<GeoWithin<String>> empty = redis.georadiusbymember(key, "Bahn", 1, GeoArgs.Unit.km, new GeoArgs().withHash().withCoordinates().withDistance().desc()); assertThat(empty).isNotEmpty(); List<GeoWithin<String>> withDistanceAndCoordinates = redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoArgs().withCoordinates().withDistance().desc()); assertThat(withDistanceAndCoordinates).hasSize(2); GeoWithin<String> weinheim = withDistanceAndCoordinates.get(0); assertThat(weinheim.getMember()).isEqualTo("Weinheim"); assertThat(weinheim.getGeohash()).isNull(); assertThat(weinheim.getDistance()).isNotNull(); assertThat(weinheim.getCoordinates()).isNotNull(); List<GeoWithin<String>> withDistanceAndHash = redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoArgs().withDistance().withHash().desc()); assertThat(withDistanceAndHash).hasSize(2); GeoWithin<String> weinheimDistanceHash = withDistanceAndHash.get(0); assertThat(weinheimDistanceHash.getMember()).isEqualTo("Weinheim"); assertThat(weinheimDistanceHash.getGeohash()).isNotNull(); assertThat(weinheimDistanceHash.getDistance()).isNotNull(); assertThat(weinheimDistanceHash.getCoordinates()).isNull(); List<GeoWithin<String>> withCoordinates = redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoArgs().withCoordinates().desc()); assertThat(withCoordinates).hasSize(2); GeoWithin<String> weinheimCoordinates = withCoordinates.get(0); assertThat(weinheimCoordinates.getMember()).isEqualTo("Weinheim"); assertThat(weinheimCoordinates.getGeohash()).isNull(); assertThat(weinheimCoordinates.getDistance()).isNull(); assertThat(weinheimCoordinates.getCoordinates()).isNotNull(); } @Test public void georadiusbymemberWithArgsAndTransaction() throws Exception { prepareGeo(); redis.multi(); redis.georadiusbymember(key, "Bahn", 1, GeoArgs.Unit.km, new GeoArgs().withHash().withCoordinates().withDistance().desc()); redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoArgs().withCoordinates().withDistance().desc()); redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoArgs().withDistance().withHash().desc()); redis.georadiusbymember(key, "Bahn", 5, GeoArgs.Unit.km, new GeoArgs().withCoordinates().desc()); List<Object> exec = redis.exec(); List<GeoWithin<String>> empty = (List) exec.get(0); assertThat(empty).isNotEmpty(); List<GeoWithin<String>> withDistanceAndCoordinates = (List) exec.get(1); assertThat(withDistanceAndCoordinates).hasSize(2); GeoWithin<String> weinheim = withDistanceAndCoordinates.get(0); assertThat(weinheim.getMember()).isEqualTo("Weinheim"); assertThat(weinheim.getGeohash()).isNull(); assertThat(weinheim.getDistance()).isNotNull(); assertThat(weinheim.getCoordinates()).isNotNull(); List<GeoWithin<String>> withDistanceAndHash = (List) exec.get(2); assertThat(withDistanceAndHash).hasSize(2); GeoWithin<String> weinheimDistanceHash = withDistanceAndHash.get(0); assertThat(weinheimDistanceHash.getMember()).isEqualTo("Weinheim"); assertThat(weinheimDistanceHash.getGeohash()).isNotNull(); assertThat(weinheimDistanceHash.getDistance()).isNotNull(); assertThat(weinheimDistanceHash.getCoordinates()).isNull(); List<GeoWithin<String>> withCoordinates = (List) exec.get(3); assertThat(withCoordinates).hasSize(2); GeoWithin<String> weinheimCoordinates = withCoordinates.get(0); assertThat(weinheimCoordinates.getMember()).isEqualTo("Weinheim"); assertThat(weinheimCoordinates.getGeohash()).isNull(); assertThat(weinheimCoordinates.getDistance()).isNull(); assertThat(weinheimCoordinates.getCoordinates()).isNotNull(); } @Test(expected = IllegalArgumentException.class) public void georadiusbymemberWithNullArgs() throws Exception { redis.georadiusbymember(key, "Bahn", 1, GeoArgs.Unit.km, (GeoArgs) null); } @Test(expected = IllegalArgumentException.class) public void georadiusStorebymemberWithNullArgs() throws Exception { redis.georadiusbymember(key, "Bahn", 1, GeoArgs.Unit.km, (GeoRadiusStoreArgs<String>) null); } }