diff --git a/Makefile b/Makefile
index 1ab5838538..809c2f2f18 100644
--- a/Makefile
+++ b/Makefile
@@ -377,8 +377,8 @@ endif
endif
endif
- [ ! -e work/redis-git ] && git clone https://github.com/antirez/redis.git --branch 3.0 --single-branch work/redis-git && cd work/redis-git|| true
- [ -e work/redis-git ] && cd work/redis-git && git reset --hard && git pull && git checkout 3.0 || true
+ [ ! -e work/redis-git ] && git clone https://github.com/antirez/redis.git --branch geo --single-branch work/redis-git && cd work/redis-git|| true
+ [ -e work/redis-git ] && cd work/redis-git && git reset --hard && git pull && git checkout geo || true
make -C work/redis-git clean
make -C work/redis-git -j4
diff --git a/src/main/java/com/lambdaworks/redis/GeoArgs.java b/src/main/java/com/lambdaworks/redis/GeoArgs.java
new file mode 100644
index 0000000000..93c68a301b
--- /dev/null
+++ b/src/main/java/com/lambdaworks/redis/GeoArgs.java
@@ -0,0 +1,79 @@
+package com.lambdaworks.redis;
+
+import com.lambdaworks.redis.protocol.CommandArgs;
+
+/**
+ * @author Mark Paluch
+ */
+public class GeoArgs {
+
+ private boolean withdistance;
+ private boolean withcoordinates;
+ private boolean withhash;
+ private boolean noproperties;
+ private Sort sort = Sort.none;
+
+ public GeoArgs withDistance() {
+ withdistance = true;
+ return this;
+ }
+
+ public GeoArgs withCoordinates() {
+ withcoordinates = true;
+ return this;
+ }
+
+ public GeoArgs withHash() {
+ withhash = true;
+ return this;
+ }
+
+ public GeoArgs noProperties() {
+ noproperties = true;
+ return this;
+ }
+
+ public GeoArgs asc() {
+ return sort(Sort.asc);
+ }
+
+ public GeoArgs desc() {
+ return sort(Sort.desc);
+ }
+
+ public GeoArgs sort(Sort sort) {
+ this.sort = sort;
+ return this;
+ }
+
+ public enum Sort {
+ asc, desc, none;
+ }
+
+ public enum Unit {
+ meter, kilometer, feet, mile;
+ }
+
+ public void build(CommandArgs args) {
+ if (withdistance) {
+ args.add("withdistance");
+ }
+
+ if (withcoordinates) {
+ args.add("withcoordinates");
+ }
+
+ if (withhash) {
+ args.add("withhash");
+ }
+
+ if (noproperties) {
+ args.add("noproperties");
+ }
+
+ if (sort != null && sort != Sort.none) {
+ args.add(sort.name());
+ }
+
+ }
+}
diff --git a/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java b/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java
index 5a489b9c5a..f2fd03bc1e 100644
--- a/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java
+++ b/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java
@@ -13,7 +13,8 @@
public interface RedisAsyncConnection extends RedisHashesAsyncConnection, RedisKeysAsyncConnection,
RedisStringsAsyncConnection, RedisListsAsyncConnection, RedisSetsAsyncConnection,
RedisSortedSetsAsyncConnection, RedisScriptingAsyncConnection, RedisServerAsyncConnection,
- RedisHLLAsyncConnection, BaseRedisAsyncConnection, RedisClusterAsyncConnection {
+ RedisHLLAsyncConnection, RedisGeoAsyncConnection, BaseRedisAsyncConnection,
+ RedisClusterAsyncConnection {
/**
* Set the default timeout for operations.
diff --git a/src/main/java/com/lambdaworks/redis/RedisAsyncConnectionImpl.java b/src/main/java/com/lambdaworks/redis/RedisAsyncConnectionImpl.java
index d2b9fb029e..6776a6e292 100644
--- a/src/main/java/com/lambdaworks/redis/RedisAsyncConnectionImpl.java
+++ b/src/main/java/com/lambdaworks/redis/RedisAsyncConnectionImpl.java
@@ -2,7 +2,7 @@
package com.lambdaworks.redis;
-import static com.lambdaworks.redis.protocol.CommandType.*;
+import static com.lambdaworks.redis.protocol.CommandType.EXEC;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -14,8 +14,18 @@
import com.lambdaworks.codec.Base16;
import com.lambdaworks.redis.codec.RedisCodec;
-import com.lambdaworks.redis.output.*;
-import com.lambdaworks.redis.protocol.*;
+import com.lambdaworks.redis.output.KeyStreamingChannel;
+import com.lambdaworks.redis.output.KeyValueStreamingChannel;
+import com.lambdaworks.redis.output.MultiOutput;
+import com.lambdaworks.redis.output.ScoredValueStreamingChannel;
+import com.lambdaworks.redis.output.ValueStreamingChannel;
+import com.lambdaworks.redis.protocol.Command;
+import com.lambdaworks.redis.protocol.CommandArgs;
+import com.lambdaworks.redis.protocol.CommandOutput;
+import com.lambdaworks.redis.protocol.CommandType;
+import com.lambdaworks.redis.protocol.ConnectionWatchdog;
+import com.lambdaworks.redis.protocol.RedisCommand;
+import com.lambdaworks.redis.protocol.SetArgs;
import io.netty.channel.ChannelHandler;
/**
@@ -1590,6 +1600,52 @@ public RedisFuture> zrangebylex(K key, String min, String max, long offs
return dispatch(commandBuilder.zrangebylex(key, min, max, offset, count));
}
+ @Override
+ public RedisFuture geoadd(K key, double latitude, double longitude, V member) {
+ return dispatch(commandBuilder.geoadd(key, latitude, longitude, member));
+ }
+
+ @Override
+ public RedisFuture geoadd(K key, Object... latLongMember) {
+ return dispatch(commandBuilder.geoadd(key, latLongMember));
+ }
+
+ @Override
+ public RedisFuture> georadius(K key, double latitude, double longitude, double distance, GeoArgs.Unit unit) {
+ return dispatch(commandBuilder.georadius(key, latitude, longitude, distance, unit.name()));
+ }
+
+ @Override
+ public RedisFuture> georadius(K key, double latitude, double longitude, double distance, GeoArgs.Unit unit,
+ GeoArgs geoArgs) {
+ return dispatch(commandBuilder.georadius(key, latitude, longitude, distance, unit.name(), geoArgs));
+ }
+
+ @Override
+ public RedisFuture> georadiusbymember(K key, V member, double distance, GeoArgs.Unit unit) {
+ return dispatch(commandBuilder.georadiusbymember(key, member, distance, unit.name()));
+ }
+
+ @Override
+ public RedisFuture> georadiusbymember(K key, V member, double distance, GeoArgs.Unit unit, GeoArgs geoArgs) {
+ return dispatch(commandBuilder.georadiusbymember(key, member, distance, unit.name(), geoArgs));
+ }
+
+ @Override
+ public RedisFuture> geoencode(double latitude, double longitude) {
+ return dispatch(commandBuilder.geoencode(latitude, longitude, null, null));
+ }
+
+ @Override
+ public RedisFuture> geoencode(double latitude, double longitude, double distance, GeoArgs.Unit unit) {
+ return dispatch(commandBuilder.geoencode(latitude, longitude, distance, unit.name()));
+ }
+
+ @Override
+ public RedisFuture> geodecode(long geohash) {
+ return dispatch(commandBuilder.geodecode(geohash));
+ }
+
protected RedisCommand dispatch(CommandType type, CommandOutput output) {
return dispatch(type, output, null);
}
diff --git a/src/main/java/com/lambdaworks/redis/RedisClusterAsyncConnection.java b/src/main/java/com/lambdaworks/redis/RedisClusterAsyncConnection.java
index 4a468574b4..583aa1edde 100644
--- a/src/main/java/com/lambdaworks/redis/RedisClusterAsyncConnection.java
+++ b/src/main/java/com/lambdaworks/redis/RedisClusterAsyncConnection.java
@@ -13,7 +13,7 @@
public interface RedisClusterAsyncConnection extends RedisHashesAsyncConnection, RedisKeysAsyncConnection,
RedisStringsAsyncConnection, RedisListsAsyncConnection, RedisSetsAsyncConnection,
RedisSortedSetsAsyncConnection, RedisScriptingAsyncConnection, RedisServerAsyncConnection,
- RedisHLLAsyncConnection, BaseRedisAsyncConnection {
+ RedisHLLAsyncConnection, RedisGeoAsyncConnection, BaseRedisAsyncConnection {
/**
* Close the connection. The connection will become not usable anymore as soon as this method was called.
diff --git a/src/main/java/com/lambdaworks/redis/RedisClusterConnection.java b/src/main/java/com/lambdaworks/redis/RedisClusterConnection.java
index a2ae47e16f..c9a66b2e0b 100644
--- a/src/main/java/com/lambdaworks/redis/RedisClusterConnection.java
+++ b/src/main/java/com/lambdaworks/redis/RedisClusterConnection.java
@@ -12,7 +12,7 @@
*/
public interface RedisClusterConnection extends RedisHashesConnection, RedisKeysConnection,
RedisStringsConnection, RedisListsConnection, RedisSetsConnection, RedisSortedSetsConnection,
- RedisScriptingConnection, RedisServerConnection, RedisHLLConnection {
+ RedisScriptingConnection, RedisServerConnection, RedisHLLConnection, RedisGeoConnection {
/**
* Close the connection. The connection will become not usable anymore as soon as this method was called.
diff --git a/src/main/java/com/lambdaworks/redis/RedisCommandBuilder.java b/src/main/java/com/lambdaworks/redis/RedisCommandBuilder.java
index bd87bce501..87140772e1 100644
--- a/src/main/java/com/lambdaworks/redis/RedisCommandBuilder.java
+++ b/src/main/java/com/lambdaworks/redis/RedisCommandBuilder.java
@@ -1,23 +1,105 @@
package com.lambdaworks.redis;
-import static com.lambdaworks.redis.protocol.CommandKeyword.*;
+import static com.lambdaworks.redis.protocol.CommandKeyword.ADDSLOTS;
+import static com.lambdaworks.redis.protocol.CommandKeyword.AFTER;
+import static com.lambdaworks.redis.protocol.CommandKeyword.AND;
+import static com.lambdaworks.redis.protocol.CommandKeyword.BEFORE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.CHANNELS;
+import static com.lambdaworks.redis.protocol.CommandKeyword.COUNT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.DELSLOTS;
+import static com.lambdaworks.redis.protocol.CommandKeyword.ENCODING;
+import static com.lambdaworks.redis.protocol.CommandKeyword.FAILOVER;
+import static com.lambdaworks.redis.protocol.CommandKeyword.FLUSH;
+import static com.lambdaworks.redis.protocol.CommandKeyword.FLUSHSLOTS;
+import static com.lambdaworks.redis.protocol.CommandKeyword.FORCE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.FORGET;
+import static com.lambdaworks.redis.protocol.CommandKeyword.GETKEYSINSLOT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.GETNAME;
+import static com.lambdaworks.redis.protocol.CommandKeyword.HARD;
+import static com.lambdaworks.redis.protocol.CommandKeyword.IDLETIME;
+import static com.lambdaworks.redis.protocol.CommandKeyword.IMPORTING;
+import static com.lambdaworks.redis.protocol.CommandKeyword.KILL;
+import static com.lambdaworks.redis.protocol.CommandKeyword.LEN;
+import static com.lambdaworks.redis.protocol.CommandKeyword.LIMIT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.LIST;
+import static com.lambdaworks.redis.protocol.CommandKeyword.LOAD;
+import static com.lambdaworks.redis.protocol.CommandKeyword.MEET;
+import static com.lambdaworks.redis.protocol.CommandKeyword.MIGRATING;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NO;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NODE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NODES;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NOSAVE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NOT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NUMPAT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.NUMSUB;
+import static com.lambdaworks.redis.protocol.CommandKeyword.ONE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.OR;
+import static com.lambdaworks.redis.protocol.CommandKeyword.PAUSE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.REFCOUNT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.REPLICATE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.RESET;
+import static com.lambdaworks.redis.protocol.CommandKeyword.RESETSTAT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.REWRITE;
+import static com.lambdaworks.redis.protocol.CommandKeyword.SEGFAULT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.SETNAME;
+import static com.lambdaworks.redis.protocol.CommandKeyword.SETSLOT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.SLAVES;
+import static com.lambdaworks.redis.protocol.CommandKeyword.SLOTS;
+import static com.lambdaworks.redis.protocol.CommandKeyword.SOFT;
+import static com.lambdaworks.redis.protocol.CommandKeyword.WITHSCORES;
+import static com.lambdaworks.redis.protocol.CommandKeyword.XOR;
import static com.lambdaworks.redis.protocol.CommandType.*;
-import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.lambdaworks.redis.codec.RedisCodec;
-import com.lambdaworks.redis.output.*;
-import com.lambdaworks.redis.protocol.*;
+import com.lambdaworks.redis.output.ArrayOutput;
+import com.lambdaworks.redis.output.BooleanListOutput;
+import com.lambdaworks.redis.output.BooleanOutput;
+import com.lambdaworks.redis.output.ByteArrayOutput;
+import com.lambdaworks.redis.output.DateOutput;
+import com.lambdaworks.redis.output.DoubleOutput;
+import com.lambdaworks.redis.output.IntegerOutput;
+import com.lambdaworks.redis.output.KeyListOutput;
+import com.lambdaworks.redis.output.KeyOutput;
+import com.lambdaworks.redis.output.KeyScanOutput;
+import com.lambdaworks.redis.output.KeyScanStreamingOutput;
+import com.lambdaworks.redis.output.KeyStreamingChannel;
+import com.lambdaworks.redis.output.KeyStreamingOutput;
+import com.lambdaworks.redis.output.KeyValueOutput;
+import com.lambdaworks.redis.output.KeyValueScanStreamingOutput;
+import com.lambdaworks.redis.output.KeyValueStreamingChannel;
+import com.lambdaworks.redis.output.KeyValueStreamingOutput;
+import com.lambdaworks.redis.output.MapOutput;
+import com.lambdaworks.redis.output.MapScanOutput;
+import com.lambdaworks.redis.output.NestedMultiOutput;
+import com.lambdaworks.redis.output.ScoredValueListOutput;
+import com.lambdaworks.redis.output.ScoredValueScanOutput;
+import com.lambdaworks.redis.output.ScoredValueScanStreamingOutput;
+import com.lambdaworks.redis.output.ScoredValueStreamingChannel;
+import com.lambdaworks.redis.output.ScoredValueStreamingOutput;
+import com.lambdaworks.redis.output.StatusOutput;
+import com.lambdaworks.redis.output.StringListOutput;
+import com.lambdaworks.redis.output.ValueListOutput;
+import com.lambdaworks.redis.output.ValueOutput;
+import com.lambdaworks.redis.output.ValueScanOutput;
+import com.lambdaworks.redis.output.ValueScanStreamingOutput;
+import com.lambdaworks.redis.output.ValueSetOutput;
+import com.lambdaworks.redis.output.ValueStreamingChannel;
+import com.lambdaworks.redis.output.ValueStreamingOutput;
+import com.lambdaworks.redis.protocol.Command;
+import com.lambdaworks.redis.protocol.CommandArgs;
+import com.lambdaworks.redis.protocol.CommandOutput;
+import com.lambdaworks.redis.protocol.RedisCommand;
+import com.lambdaworks.redis.protocol.SetArgs;
/**
- *
- * @author Mark Paluch
* @param
* @param
+ * @author Mark Paluch
*/
class RedisCommandBuilder extends BaseRedisCommandBuilder {
@@ -1638,6 +1720,78 @@ public Command clusterReset(boolean hard) {
return createCommand(CLUSTER, new StatusOutput(codec), args);
}
+ public Command geoadd(K key, double latitude, double longitude, V member) {
+ CommandArgs args = new CommandArgs(codec).addKey(key).add(latitude).add(longitude).addValue(member);
+ return createCommand(GEOADD, new IntegerOutput(codec), args);
+ }
+
+ public Command geoadd(K key, Object[] latLongMember) {
+
+ assertNotEmpty(latLongMember, "latLongMember " + MUST_NOT_BE_EMPTY);
+ assertNoNullElements(latLongMember, "latLongMember " + MUST_NOT_CONTAIN_NULL_ELEMENTS);
+ assertTrue(
+ latLongMember.length % 3 == 0,
+ "latLongMember.length must be a multiple of 3 and contain a "
+ + "sequence of latitude1, longitude1, member1, latitude2, longitude2, member2, ... latitudeN, longitudeN, memberN");
+
+ CommandArgs args = new CommandArgs(codec).addKey(key);
+
+ for (int i = 0; i < latLongMember.length; i += 3) {
+ args.add((Double) latLongMember[i]);
+ args.add((Double) latLongMember[i + 1]);
+ args.addValue((V) latLongMember[i + 2]);
+ }
+
+ return createCommand(GEOADD, new IntegerOutput(codec), args);
+ }
+
+ public Command> georadius(K key, double latitude, double longitude, double distance, String unit) {
+ CommandArgs args = new CommandArgs(codec).addKey(key).add(latitude).add(longitude).add(distance).add(unit);
+ return createCommand(GEORADIUS, new ValueSetOutput(codec), args);
+ }
+
+ public Command> georadius(K key, double latitude, double longitude, double distance, String unit,
+ GeoArgs geoArgs) {
+
+ CommandArgs args = new CommandArgs(codec).addKey(key).add(latitude).add(longitude).add(distance).add(unit);
+
+ if (geoArgs != null) {
+ geoArgs.build(args);
+ }
+
+ return createCommand(GEORADIUS, new NestedMultiOutput(codec), args);
+ }
+
+ public Command> georadiusbymember(K key, V member, double distance, String unit) {
+ CommandArgs args = new CommandArgs(codec).addKey(key).addValue(member).add(distance).add(unit);
+ return createCommand(GEORADIUSBYMEMBER, new ValueSetOutput(codec), args);
+ }
+
+ public Command> georadiusbymember(K key, V member, double distance, String unit, GeoArgs geoArgs) {
+ CommandArgs args = new CommandArgs(codec).addKey(key).addValue(member).add(distance).add(unit);
+
+ if (geoArgs != null) {
+ geoArgs.build(args);
+ }
+
+ return createCommand(GEORADIUSBYMEMBER, new NestedMultiOutput(codec), args);
+ }
+
+ public Command> geoencode(double latitude, double longitude, Double distance, String unit) {
+ CommandArgs args = new CommandArgs(codec).add(latitude).add(longitude);
+
+ if (distance != null && unit != null) {
+ args.add(distance).add(unit);
+ }
+ return createCommand(GEOENCODE, new NestedMultiOutput(codec), args);
+ }
+
+ public Command> geodecode(long geohash) {
+ CommandArgs args = new CommandArgs(codec).add(geohash);
+
+ return createCommand(GEODECODE, new NestedMultiOutput(codec), args);
+ }
+
/**
* Assert that a string is not empty, it must not be {@code null} and it must not be empty.
*
@@ -1653,7 +1807,7 @@ protected static void assertNotEmpty(String string, String message) {
/**
* Assert that an object is not {@code null} .
- *
+ *
* @param object the object to check
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object is {@code null}
@@ -1666,7 +1820,7 @@ public static void assertNotNull(Object object, String message) {
/**
* Assert that an array has elements; that is, it must not be {@code null} and must have at least one element.
- *
+ *
* @param array the array to check
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object array is {@code null} or has no elements
@@ -1692,7 +1846,7 @@ protected static void assertNotEmpty(int[] array, String message) {
/**
* Assert that an array has no null elements.
- *
+ *
* @param array the array to check
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object array contains a {@code null} element
@@ -1709,7 +1863,7 @@ public static void assertNoNullElements(Object[] array, String message) {
/**
* Assert that {@code value} is {@literal true}.
- *
+ *
* @param value the value to check
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object array contains a {@code null} element
diff --git a/src/main/java/com/lambdaworks/redis/RedisConnection.java b/src/main/java/com/lambdaworks/redis/RedisConnection.java
index a8dc7d856c..670c8af4a0 100644
--- a/src/main/java/com/lambdaworks/redis/RedisConnection.java
+++ b/src/main/java/com/lambdaworks/redis/RedisConnection.java
@@ -13,8 +13,8 @@
*/
public interface RedisConnection extends RedisHashesConnection, RedisKeysConnection,
RedisStringsConnection, RedisListsConnection, RedisSetsConnection, RedisSortedSetsConnection,
- RedisScriptingConnection, RedisServerConnection, RedisHLLConnection, BaseRedisConnection,
- RedisClusterConnection {
+ RedisScriptingConnection, RedisServerConnection, RedisHLLConnection, RedisGeoConnection,
+ BaseRedisConnection, RedisClusterConnection {
/**
* Set the default timeout for operations.
diff --git a/src/main/java/com/lambdaworks/redis/RedisGeoAsyncConnection.java b/src/main/java/com/lambdaworks/redis/RedisGeoAsyncConnection.java
new file mode 100644
index 0000000000..aa78fb7aea
--- /dev/null
+++ b/src/main/java/com/lambdaworks/redis/RedisGeoAsyncConnection.java
@@ -0,0 +1,114 @@
+package com.lambdaworks.redis;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Synchronous executed commands for Geo-Commands.
+ *
+ * @author Mark Paluch
+ * @since 3.3
+ */
+public interface RedisGeoAsyncConnection {
+
+ /**
+ * Single geo add.
+ *
+ * @param key
+ * @param latitude
+ * @param longitude
+ * @param member
+ * @return 1 if member is new or 0 if member is updated
+ */
+ RedisFuture geoadd(K key, double latitude, double longitude, V member);
+
+ /**
+ * Multi geo add
+ *
+ * @param key
+ * @param latLonMember triplets of double latitude, double longitude and V member
+ * @return count of members submitted
+ */
+ RedisFuture geoadd(K key, Object... latLonMember);
+
+ /**
+ * Retrieve members selected by distance with the center of {@code latitude} and {@code longitude}.
+ *
+ * @param key
+ * @param latitude
+ * @param longitude
+ * @param distance
+ * @param unit
+ * @return
+ */
+ RedisFuture> georadius(K key, double latitude, double longitude, double distance, GeoArgs.Unit unit);
+
+ /**
+ * Retrieve members selected by distance with the center of {@code latitude} and {@code longitude}.
+ *
+ * @param key
+ * @param latitude
+ * @param longitude
+ * @param distance
+ * @param unit
+ * @return
+ */
+ RedisFuture> georadius(K key, double latitude, double longitude, double distance, GeoArgs.Unit unit,
+ GeoArgs geoArgs);
+
+ /**
+ * Retrieve members selected by distance with the center of {@code member}.
+ *
+ * @param key
+ * @param member
+ * @param distance
+ * @param unit
+ * @return
+ */
+ RedisFuture> georadiusbymember(K key, V member, double distance, GeoArgs.Unit unit);
+
+ /**
+ *
+ * Retrieve members selected by distance with the center of {@code member}.
+ *
+ * @param key
+ * @param member
+ * @param distance
+ * @param unit
+ * @return
+ */
+ RedisFuture> georadiusbymember(K key, V member, double distance, GeoArgs.Unit unit, GeoArgs geoArgs);
+
+ /**
+ *
+ * Encode latitude and longitude to highest geohash accuracy.
+ *
+ * @param latitude
+ * @param longitude
+ * @return nested multi-bulk reply with 1: the 52-bit geohash integer for your latitude longitude, 2: The minimum corner of
+ * your geohash, 3: The maximum corner of your geohash, 4: The averaged center of your geohash.
+ */
+ RedisFuture> geoencode(double latitude, double longitude);
+
+ /**
+ *
+ * Encode latitude and longitude to highest geohash accuracy.
+ *
+ * @param latitude
+ * @param longitude
+ * @param distance
+ * @param unit
+ * @return nested multi-bulk reply with 1: the 52-bit geohash integer for your latitude longitude, 2: The minimum corner of
+ * your geohash, 3: The maximum corner of your geohash, 4: The averaged center of your geohash.
+ */
+ RedisFuture> geoencode(double latitude, double longitude, double distance, GeoArgs.Unit unit);
+
+ /**
+ *
+ * Decode geohash.
+ *
+ * @param geohash
+ * @return nested multi-bulk with 1: minimum decoded corner, 2: maximum decoded corner, 3: averaged center of bounding box.
+ */
+ RedisFuture> geodecode(long geohash);
+}
diff --git a/src/main/java/com/lambdaworks/redis/RedisGeoConnection.java b/src/main/java/com/lambdaworks/redis/RedisGeoConnection.java
new file mode 100644
index 0000000000..d1d44cb3cc
--- /dev/null
+++ b/src/main/java/com/lambdaworks/redis/RedisGeoConnection.java
@@ -0,0 +1,113 @@
+package com.lambdaworks.redis;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Synchronous executed commands for Geo-Commands.
+ *
+ * @author Mark Paluch
+ * @since 3.3
+ */
+public interface RedisGeoConnection {
+
+ /**
+ * Single geo add.
+ *
+ * @param key
+ * @param latitude
+ * @param longitude
+ * @param member
+ * @return
+ */
+ Long geoadd(K key, double latitude, double longitude, V member);
+
+ /**
+ * Multi geo add
+ *
+ * @param key
+ * @param latLonMember triplets of double latitude, double longitude and V member
+ * @return
+ */
+ Long geoadd(K key, Object... latLonMember);
+
+ /**
+ * Retrieve members selected by distance with the center of {@code latitude} and {@code longitude}.
+ *
+ * @param key
+ * @param latitude
+ * @param longitude
+ * @param distance
+ * @param unit
+ * @return
+ */
+ Set georadius(K key, double latitude, double longitude, double distance, GeoArgs.Unit unit);
+
+ /**
+ * Retrieve members selected by distance with the center of {@code latitude} and {@code longitude}.
+ *
+ * @param key
+ * @param latitude
+ * @param longitude
+ * @param distance
+ * @param unit
+ * @return
+ */
+ List