Add support for GEOSEARCH/GEOSEARCHSTORE commands.
Supported through Lettuce only. GeoOperations support GEOSEARCH for now. Closes: #2043 Original Pull Request: #2113
This commit is contained in:
committed by
Christoph Strobl
parent
2f6dc3e79e
commit
ce52baff98
@@ -2120,6 +2120,14 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return serializer.serialize(data);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private GeoReference<byte[]> serialize(GeoReference<String> data) {
|
||||
return data instanceof GeoReference.GeoSearchMemberReference
|
||||
? GeoReference
|
||||
.fromMember(serializer.serialize(((GeoReference.GeoSearchMemberReference<String>) data).getMember()))
|
||||
: (GeoReference) data;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private StreamOffset<byte[]>[] serialize(StreamOffset<String>[] offsets) {
|
||||
|
||||
@@ -3886,6 +3894,50 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return geoRemove(serialize(key), serializeMulti(members));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearch(byte[], byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoSearch(byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args) {
|
||||
return convertAndReturn(delegate.geoSearch(key, reference, predicate, args), Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearchStore(byte[], byte[], byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long geoSearchStore(byte[] destKey, byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return convertAndReturn(delegate.geoSearchStore(destKey, key, reference, predicate, args),
|
||||
Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#geoSearch(java.lang.String, java.lang.String, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<String>> geoSearch(String key, GeoReference<String> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args) {
|
||||
return convertAndReturn(delegate.geoSearch(serialize(key), serialize(reference), predicate, args),
|
||||
byteGeoResultsToStringGeoResults);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#geoSearchStore(java.lang.String, java.lang.String, java.lang.String, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long geoSearchStore(String destKey, String key, GeoReference<String> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return convertAndReturn(
|
||||
delegate.geoSearchStore(serialize(destKey), serialize(key), serialize(reference), predicate, args),
|
||||
Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisConnection#closePipeline()
|
||||
|
||||
@@ -1540,6 +1540,22 @@ public interface DefaultedRedisConnection extends RedisConnection {
|
||||
return geoCommands().geoRemove(key, members);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#geoCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default GeoResults<GeoLocation<byte[]>> geoSearch(byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args) {
|
||||
return geoCommands().geoSearch(key, reference, predicate, args);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#geoCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default Long geoSearchStore(byte[] destKey, byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return geoCommands().geoSearchStore(destKey, key, reference, predicate, args);
|
||||
}
|
||||
|
||||
// HLL COMMANDS
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#hyperLogLogCommands()}. */
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection;
|
||||
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -27,6 +29,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.geo.Circle;
|
||||
import org.springframework.data.geo.Distance;
|
||||
@@ -37,9 +40,6 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Command
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.Flag;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -1239,4 +1239,261 @@ public interface ReactiveGeoCommands {
|
||||
*/
|
||||
Flux<CommandResponse<GeoRadiusByMemberCommand, Flux<GeoResult<GeoLocation<ByteBuffer>>>>> geoRadiusByMember(
|
||||
Publisher<GeoRadiusByMemberCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code GEOSEARCH} command parameters.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
class GeoSearchCommand extends KeyCommand {
|
||||
|
||||
private final @Nullable GeoReference<ByteBuffer> reference;
|
||||
private final @Nullable GeoShape shape;
|
||||
private final @Nullable GeoSearchCommandArgs args;
|
||||
|
||||
private GeoSearchCommand(@Nullable ByteBuffer key, @Nullable GeoReference<ByteBuffer> reference,
|
||||
@Nullable GeoShape shape, @Nullable GeoSearchCommandArgs args) {
|
||||
super(key);
|
||||
this.reference = reference;
|
||||
this.shape = shape;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link GeoSearchCommand} given a {@link GeoShape}.
|
||||
*
|
||||
* @param shape must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchCommand} for a {@link GeoShape}.
|
||||
*/
|
||||
public static GeoSearchCommand within(GeoShape shape) {
|
||||
|
||||
Assert.notNull(shape, "GeoShape must not be null!");
|
||||
|
||||
return new GeoSearchCommand(null, null, shape, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the geoset {@literal key}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchCommand} with {@literal key} applied.
|
||||
*/
|
||||
public GeoSearchCommand at(GeoReference<ByteBuffer> reference) {
|
||||
|
||||
Assert.notNull(reference, "GeoReference must not be null!");
|
||||
|
||||
return new GeoSearchCommand(getKey(), reference, getShape(), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the geoset {@literal key}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchCommand} with {@literal key} applied.
|
||||
*/
|
||||
public GeoSearchCommand in(ByteBuffer key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return new GeoSearchCommand(key, getReference(), getShape(), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command {@literal args}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param args must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchCommand} with {@literal args} applied.
|
||||
*/
|
||||
public GeoSearchCommand with(GeoSearchCommandArgs args) {
|
||||
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
return new GeoSearchCommand(getKey(), getReference(), getShape(), args);
|
||||
}
|
||||
|
||||
public Optional<GeoSearchCommandArgs> getArgs() {
|
||||
return Optional.ofNullable(args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeoReference<ByteBuffer> getReference() {
|
||||
return reference;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeoShape getShape() {
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code GEOSEARCHSTORE} command parameters.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
class GeoSearchStoreCommand extends KeyCommand {
|
||||
|
||||
private final @Nullable ByteBuffer destKey;
|
||||
private final @Nullable GeoReference<ByteBuffer> reference;
|
||||
private final @Nullable GeoShape shape;
|
||||
private final @Nullable GeoSearchStoreCommandArgs args;
|
||||
|
||||
private GeoSearchStoreCommand(@Nullable ByteBuffer key, @Nullable ByteBuffer destKey,
|
||||
@Nullable GeoReference<ByteBuffer> reference, @Nullable GeoShape shape,
|
||||
@Nullable GeoSearchStoreCommandArgs args) {
|
||||
super(key);
|
||||
this.destKey = destKey;
|
||||
this.reference = reference;
|
||||
this.shape = shape;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link GeoSearchStoreCommand} given a {@link GeoShape}.
|
||||
*
|
||||
* @param shape must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchStoreCommand} for a {@link GeoShape}.
|
||||
*/
|
||||
public static GeoSearchStoreCommand within(GeoShape shape) {
|
||||
|
||||
Assert.notNull(shape, "GeoShape must not be null!");
|
||||
|
||||
return new GeoSearchStoreCommand(null, null, null, shape, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the geoset {@literal key}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchStoreCommand} with {@literal key} applied.
|
||||
*/
|
||||
public GeoSearchStoreCommand at(GeoReference<ByteBuffer> reference) {
|
||||
|
||||
Assert.notNull(reference, "GeoReference must not be null!");
|
||||
|
||||
return new GeoSearchStoreCommand(getKey(), getDestKey(), reference, getShape(), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the geoset {@literal key}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchStoreCommand} with {@literal key} applied.
|
||||
*/
|
||||
public GeoSearchStoreCommand in(ByteBuffer key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return new GeoSearchStoreCommand(key, getDestKey(), getReference(), getShape(), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the geoset {@literal destKey}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchStoreCommand} with {@literal destKey} applied.
|
||||
*/
|
||||
public GeoSearchStoreCommand storeAt(ByteBuffer destKey) {
|
||||
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
|
||||
return new GeoSearchStoreCommand(getKey(), destKey, getReference(), getShape(), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command {@literal args}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param args must not be {@literal null}.
|
||||
* @return a new {@link GeoSearchStoreCommand} with {@literal args} applied.
|
||||
*/
|
||||
public GeoSearchStoreCommand with(GeoSearchStoreCommandArgs args) {
|
||||
|
||||
Assert.notNull(args, "Args must not be null!");
|
||||
|
||||
return new GeoSearchStoreCommand(getKey(), getDestKey(), getReference(), getShape(), args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ByteBuffer getDestKey() {
|
||||
return destKey;
|
||||
}
|
||||
|
||||
public Optional<GeoSearchStoreCommandArgs> getArgs() {
|
||||
return Optional.ofNullable(args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeoReference<ByteBuffer> getReference() {
|
||||
return reference;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeoShape getShape() {
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the members of a geo set which are within the borders of the area specified by a given {@link GeoShape
|
||||
* shape}. The query's center point is provided by {@link GeoReference}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param shape must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Flux<GeoResult<GeoLocation<ByteBuffer>>> geoSearch(ByteBuffer key, GeoReference<ByteBuffer> reference,
|
||||
GeoShape shape, GeoSearchCommandArgs args) {
|
||||
return geoSearch(Mono.just(GeoSearchCommand.within(shape).in(key).at(reference).with(args)))
|
||||
.flatMap(CommandResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within given {@link GeoShape} from {@link GeoReference} applying given parameters.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
Flux<CommandResponse<GeoSearchCommand, Flux<GeoResult<GeoLocation<ByteBuffer>>>>> geoSearch(
|
||||
Publisher<GeoSearchCommand> commands);
|
||||
|
||||
/**
|
||||
* Query the members of a geo set which are within the borders of the area specified by a given {@link GeoShape shape}
|
||||
* and store the result at {@code destKey}. The query's center point is provided by {@link GeoReference}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param shape must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Mono<Long> geoSearchStore(ByteBuffer destKey, ByteBuffer key, GeoReference<ByteBuffer> reference,
|
||||
GeoShape shape, GeoSearchStoreCommandArgs args) {
|
||||
return geoSearchStore(
|
||||
Mono.just(GeoSearchStoreCommand.within(shape).in(key).storeAt(destKey).at(reference).with(args))).next()
|
||||
.map(CommandResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the {@literal member}s within given {@link GeoShape} from {@link GeoReference} applying given parameters in a
|
||||
* new geo set.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
Flux<NumericResponse<GeoSearchStoreCommand, Long>> geoSearchStore(Publisher<GeoSearchStoreCommand> commands);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection;
|
||||
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -26,6 +28,7 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.geo.Shape;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -215,28 +218,159 @@ public interface RedisGeoCommands {
|
||||
@Nullable
|
||||
Long geoRemove(byte[] key, byte[]... members);
|
||||
|
||||
/**
|
||||
* Return the members of a geo set which are within the borders of the area specified by a given {@link GeoShape
|
||||
* shape}. The query's center point is provided by {@link GeoReference}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param predicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
GeoResults<GeoLocation<byte[]>> geoSearch(byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args);
|
||||
|
||||
/**
|
||||
* Query the members of a geo set which are within the borders of the area specified by a given {@link GeoShape shape}
|
||||
* and store the result at {@code destKey}. The query's center point is provided by {@link GeoReference}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param predicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long geoSearchStore(byte[] destKey, byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args);
|
||||
|
||||
/**
|
||||
* Search predicate for {@code GEOSEARCH} and {@code GEOSEARCHSTORE} commands.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
interface GeoShape {
|
||||
|
||||
/**
|
||||
* Create a shape used as predicate for geo queries from a {@link Distance radius} around the query center point.
|
||||
*
|
||||
* @param radius
|
||||
* @return
|
||||
*/
|
||||
static GeoShape byRadius(Distance radius) {
|
||||
return new RadiusShape(radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shape used as predicate for geo queries from a bounding box with specified by {@code width} and
|
||||
* {@code height}.
|
||||
*
|
||||
* @param width must not be {@literal null}.
|
||||
* @param height must not be {@literal null}.
|
||||
* @param distanceUnit must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
static GeoShape byBox(double width, double height, DistanceUnit distanceUnit) {
|
||||
return byBox(new BoundingBox(width, height, distanceUnit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shape used as predicate for geo queries from a {@link BoundingBox}.
|
||||
*
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
static GeoShape byBox(BoundingBox boundingBox) {
|
||||
return new BoxShape(boundingBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* The metric used for this geo predicate.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Metric getMetric();
|
||||
}
|
||||
|
||||
/**
|
||||
* Radius defined by {@link Distance}.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
class RadiusShape implements GeoShape {
|
||||
|
||||
private final Distance radius;
|
||||
|
||||
public RadiusShape(Distance radius) {
|
||||
|
||||
Assert.notNull(radius, "Distance must not be null");
|
||||
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public Distance getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metric getMetric() {
|
||||
return radius.getMetric();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bounding box defined by width and height.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
class BoxShape implements GeoShape {
|
||||
|
||||
private final BoundingBox boundingBox;
|
||||
|
||||
public BoxShape(BoundingBox boundingBox) {
|
||||
|
||||
Assert.notNull(boundingBox, "BoundingBox must not be null");
|
||||
|
||||
this.boundingBox = boundingBox;
|
||||
}
|
||||
|
||||
public BoundingBox getBoundingBox() {
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metric getMetric() {
|
||||
return boundingBox.getHeight().getMetric();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional arguments (like count/sort/...) to be used with {@link RedisGeoCommands}.
|
||||
*
|
||||
* @author Ninad Divadkar
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
* @author Mark Paluch
|
||||
* @since 2.6
|
||||
*/
|
||||
class GeoRadiusCommandArgs implements Cloneable {
|
||||
class GeoSearchCommandArgs implements Cloneable {
|
||||
|
||||
Set<Flag> flags = new LinkedHashSet<>(2, 1);
|
||||
@Nullable Long limit;
|
||||
@Nullable Direction sortDirection;
|
||||
|
||||
private GeoRadiusCommandArgs() {}
|
||||
private GeoSearchCommandArgs() {}
|
||||
|
||||
/**
|
||||
* Create new {@link GeoRadiusCommandArgs}.
|
||||
* Create new {@link GeoSearchCommandArgs}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public static GeoRadiusCommandArgs newGeoRadiusArgs() {
|
||||
return new GeoRadiusCommandArgs();
|
||||
public static GeoSearchCommandArgs newGeoSearchArgs() {
|
||||
return new GeoSearchCommandArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,7 +378,7 @@ public interface RedisGeoCommands {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GeoRadiusCommandArgs includeCoordinates() {
|
||||
public GeoSearchCommandArgs includeCoordinates() {
|
||||
|
||||
flags.add(Flag.WITHCOORD);
|
||||
return this;
|
||||
@@ -255,21 +389,32 @@ public interface RedisGeoCommands {
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs includeDistance() {
|
||||
public GeoSearchCommandArgs includeDistance() {
|
||||
|
||||
flags.add(Flag.WITHDIST);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a sort direction.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchCommandArgs sort(Direction direction) {
|
||||
|
||||
Assert.notNull(direction, "Sort direction must not be null");
|
||||
|
||||
this.sortDirection = direction;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort returned items from the nearest to the furthest, relative to the center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs sortAscending() {
|
||||
|
||||
sortDirection = Direction.ASC;
|
||||
return this;
|
||||
public GeoSearchCommandArgs sortAscending() {
|
||||
return sort(Direction.ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,10 +422,8 @@ public interface RedisGeoCommands {
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs sortDescending() {
|
||||
|
||||
sortDirection = Direction.DESC;
|
||||
return this;
|
||||
public GeoSearchCommandArgs sortDescending() {
|
||||
return sort(Direction.DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,13 +432,28 @@ public interface RedisGeoCommands {
|
||||
* @param count
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs limit(long count) {
|
||||
public GeoSearchCommandArgs limit(long count) {
|
||||
|
||||
Assert.isTrue(count > 0, "Count has to positive value.");
|
||||
limit = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the results to the first N matching items.
|
||||
*
|
||||
* @param count
|
||||
* @param any
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchCommandArgs limit(long count, boolean any) {
|
||||
|
||||
Assert.isTrue(count > 0, "Count has to positive value.");
|
||||
limit = count;
|
||||
flags.add(Flag.ANY);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
@@ -331,8 +489,248 @@ public interface RedisGeoCommands {
|
||||
return limit != null;
|
||||
}
|
||||
|
||||
public boolean hasAnyLimit() {
|
||||
return hasLimit() && flags.contains(Flag.ANY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GeoSearchCommandArgs clone() {
|
||||
|
||||
GeoSearchCommandArgs tmp = new GeoSearchCommandArgs();
|
||||
tmp.flags = this.flags != null ? new LinkedHashSet<>(this.flags) : new LinkedHashSet<>(2);
|
||||
tmp.limit = this.limit;
|
||||
tmp.sortDirection = this.sortDirection;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional arguments (like count/sort/...) to be used with {@link RedisGeoCommands}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.6
|
||||
*/
|
||||
class GeoSearchStoreCommandArgs implements Cloneable {
|
||||
|
||||
Set<Flag> flags = new LinkedHashSet<>(2, 1);
|
||||
@Nullable Long limit;
|
||||
@Nullable Direction sortDirection;
|
||||
|
||||
private GeoSearchStoreCommandArgs() {}
|
||||
|
||||
/**
|
||||
* Create new {@link GeoSearchStoreCommandArgs}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public static GeoSearchStoreCommandArgs newGeoSearchStoreArgs() {
|
||||
return new GeoSearchStoreCommandArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Flag#STOREDIST} flag to also store the distance of the returned items from the specified center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchStoreCommandArgs storeDistance() {
|
||||
|
||||
flags.add(Flag.STOREDIST);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a sort direction.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchStoreCommandArgs sort(Direction direction) {
|
||||
|
||||
Assert.notNull(direction, "Sort direction must not be null");
|
||||
|
||||
sortDirection = Direction.ASC;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort returned items from the nearest to the furthest, relative to the center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchStoreCommandArgs sortAscending() {
|
||||
return sort(Direction.ASC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort returned items from the furthest to the nearest, relative to the center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchStoreCommandArgs sortDescending() {
|
||||
return sort(Direction.DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the results to the first N matching items.
|
||||
*
|
||||
* @param count
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchStoreCommandArgs limit(long count) {
|
||||
|
||||
Assert.isTrue(count > 0, "Count has to positive value.");
|
||||
limit = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the results to the first N matching items.
|
||||
*
|
||||
* @param count
|
||||
* @param any
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoSearchStoreCommandArgs limit(long count, boolean any) {
|
||||
|
||||
Assert.isTrue(count > 0, "Count has to positive value.");
|
||||
limit = count;
|
||||
flags.add(Flag.ANY);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public Set<Flag> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
public Long getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
public Direction getSortDirection() {
|
||||
return sortDirection;
|
||||
}
|
||||
|
||||
public boolean isStoreDistance() {
|
||||
return flags.contains(Flag.STOREDIST);
|
||||
}
|
||||
|
||||
public boolean hasSortDirection() {
|
||||
return sortDirection != null;
|
||||
}
|
||||
|
||||
public boolean hasLimit() {
|
||||
return limit != null;
|
||||
}
|
||||
|
||||
public boolean hasAnyLimit() {
|
||||
return hasLimit() && flags.contains(Flag.ANY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GeoSearchStoreCommandArgs clone() {
|
||||
|
||||
GeoSearchStoreCommandArgs tmp = new GeoSearchStoreCommandArgs();
|
||||
tmp.flags = this.flags != null ? new LinkedHashSet<>(this.flags) : new LinkedHashSet<>(2);
|
||||
tmp.limit = this.limit;
|
||||
tmp.sortDirection = this.sortDirection;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional arguments (like count/sort/...) to be used with {@link RedisGeoCommands}.
|
||||
*
|
||||
* @author Ninad Divadkar
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
*/
|
||||
class GeoRadiusCommandArgs extends GeoSearchCommandArgs implements Cloneable {
|
||||
|
||||
private GeoRadiusCommandArgs() {}
|
||||
|
||||
/**
|
||||
* Create new {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public static GeoRadiusCommandArgs newGeoRadiusArgs() {
|
||||
return new GeoRadiusCommandArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Flag#WITHCOORD} flag to also return the longitude, latitude coordinates of the matching items.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GeoRadiusCommandArgs includeCoordinates() {
|
||||
super.includeCoordinates();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Flag#WITHDIST} flag to also return the distance of the returned items from the specified center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs includeDistance() {
|
||||
super.includeDistance();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a sort direction.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.6
|
||||
*/
|
||||
public GeoRadiusCommandArgs sort(Direction direction) {
|
||||
super.sort(direction);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort returned items from the nearest to the furthest, relative to the center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs sortAscending() {
|
||||
super.sortAscending();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort returned items from the furthest to the nearest, relative to the center.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs sortDescending() {
|
||||
super.sortDescending();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the results to the first N matching items.
|
||||
*
|
||||
* @param count
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public GeoRadiusCommandArgs limit(long count) {
|
||||
super.limit(count);
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum Flag {
|
||||
WITHCOORD, WITHDIST
|
||||
WITHCOORD, WITHDIST, ANY, STOREDIST
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -346,6 +744,193 @@ public interface RedisGeoCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference point for {@code GEOSEARCH} and {@code GEOSEARCHSTORE} commands. Provides factory methods to create
|
||||
* {@link GeoReference} from geo-set members or reference points.
|
||||
*
|
||||
* @param <T>
|
||||
* @since 2.6
|
||||
*/
|
||||
class GeoReference<T> {
|
||||
|
||||
/**
|
||||
* Creates a {@link GeoReference} from a geoset member.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GeoReference<T> fromMember(T member) {
|
||||
|
||||
Assert.notNull(member, "Geoset member must not be null");
|
||||
|
||||
return new GeoSearchMemberReference<>(member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GeoReference} from a {@link GeoLocation geoset member}.
|
||||
*
|
||||
* @param member must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GeoReference<T> fromMember(GeoLocation<T> member) {
|
||||
|
||||
Assert.notNull(member, "GeoLocation must not be null");
|
||||
|
||||
return new GeoSearchMemberReference<>(member.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GeoReference} from a {@link Circle#getCenter() circle center point} .
|
||||
*
|
||||
* @param within must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GeoReference<T> fromCircle(Circle within) {
|
||||
|
||||
Assert.notNull(within, "Circle must not be null");
|
||||
|
||||
return fromCoordinate(within.getCenter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GeoReference} from a WGS84 longitude/latitude coordinate.
|
||||
*
|
||||
* @param longitude
|
||||
* @param latitude
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GeoReference<T> fromCoordinate(double longitude, double latitude) {
|
||||
return new GeoSearchCoordinateReference<>(longitude, latitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GeoReference} from a WGS84 longitude/latitude coordinate.
|
||||
*
|
||||
* @param location must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GeoReference<T> fromCoordinate(GeoLocation<?> location) {
|
||||
|
||||
Assert.notNull(location, "GeoLocation must not be null");
|
||||
Assert.notNull(location.getPoint(), "GeoLocation point must not be null");
|
||||
|
||||
return fromCoordinate(location.getPoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GeoReference} from a WGS84 longitude/latitude coordinate.
|
||||
*
|
||||
* @param point must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GeoReference<T> fromCoordinate(Point point) {
|
||||
|
||||
Assert.notNull(point, "Reference point must not be null");
|
||||
|
||||
return fromCoordinate(point.getX(), point.getY());
|
||||
}
|
||||
|
||||
public static class GeoSearchMemberReference<T> extends GeoReference<T> {
|
||||
|
||||
private final T member;
|
||||
|
||||
public GeoSearchMemberReference(T member) {
|
||||
this.member = member;
|
||||
}
|
||||
|
||||
public T getMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof GeoSearchMemberReference)) {
|
||||
return false;
|
||||
}
|
||||
GeoSearchMemberReference<?> that = (GeoSearchMemberReference<?>) o;
|
||||
return ObjectUtils.nullSafeEquals(member, that.member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getSimpleName());
|
||||
sb.append(" [member=").append(member);
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GeoSearchCoordinateReference<T> extends GeoReference<T> {
|
||||
|
||||
private final double longitude;
|
||||
private final double latitude;
|
||||
|
||||
public GeoSearchCoordinateReference(double longitude, double latitude) {
|
||||
this.longitude = longitude;
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof GeoSearchCoordinateReference)) {
|
||||
return false;
|
||||
}
|
||||
GeoSearchCoordinateReference<?> that = (GeoSearchCoordinateReference<?>) o;
|
||||
if (longitude != that.longitude) {
|
||||
return false;
|
||||
}
|
||||
return latitude == that.latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(longitude);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(latitude);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getSimpleName());
|
||||
sb.append(" [").append(longitude);
|
||||
sb.append(",").append(latitude);
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link GeoLocation} representing a {@link Point} associated with a {@literal name}.
|
||||
*
|
||||
@@ -448,4 +1033,100 @@ public interface RedisGeoCommands {
|
||||
return abbreviation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a geospatial bounding box defined by width and height.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.6
|
||||
*/
|
||||
class BoundingBox implements Shape {
|
||||
|
||||
private static final long serialVersionUID = 5215611530535947924L;
|
||||
|
||||
private final Distance width;
|
||||
private final Distance height;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BoundingBox} from the given width and height. Both distances must use the same
|
||||
* {@link Metric}.
|
||||
*
|
||||
* @param width must not be {@literal null}.
|
||||
* @param height must not be {@literal null}.
|
||||
*/
|
||||
public BoundingBox(Distance width, Distance height) {
|
||||
|
||||
Assert.notNull(width, "Width must not be null!");
|
||||
Assert.notNull(height, "Height must not be null!");
|
||||
Assert.isTrue(width.getMetric().equals(height.getMetric()), "Metric for width and height must be the same!");
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BoundingBox} from the given width, height and {@link Metric}.
|
||||
*
|
||||
* @param width
|
||||
* @param height
|
||||
* @param metric must not be {@literal null}.
|
||||
*/
|
||||
public BoundingBox(double width, double height, Metric metric) {
|
||||
this(new Distance(width, metric), new Distance(height, metric));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of this bounding box.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Distance getWidth() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of this bounding box.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Distance getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(width);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(height);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BoundingBox)) {
|
||||
return false;
|
||||
}
|
||||
BoundingBox that = (BoundingBox) o;
|
||||
if (!ObjectUtils.nullSafeEquals(width, that.width)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(height, that.height);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Bounding box: [width=%s, height=%s]", width, height);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2425,6 +2425,40 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
*/
|
||||
Long geoRemove(String key, String... members);
|
||||
|
||||
/**
|
||||
* Return the members of a geo set which are within the borders of the area specified by a given {@link GeoShape
|
||||
* shape}. The query's center point is provided by
|
||||
* {@link org.springframework.data.redis.connection.RedisGeoCommands.GeoReference}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param predicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
GeoResults<GeoLocation<String>> geoSearch(String key, GeoReference<String> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args);
|
||||
|
||||
/**
|
||||
* Query the members of a geo set which are within the borders of the area specified by a given {@link GeoShape shape}
|
||||
* and store the result at {@code destKey}. The query's center point is provided by
|
||||
* {@link org.springframework.data.redis.connection.RedisGeoCommands.GeoReference}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param predicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long geoSearchStore(String destKey, String key, GeoReference<String> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Methods dealing with Redis Pub/Sub
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@@ -281,6 +281,26 @@ class JedisClusterGeoCommands implements RedisGeoCommands {
|
||||
return connection.zRem(key, members);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearch(byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoSearch(byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args) {
|
||||
throw new UnsupportedOperationException("GEOSEARCH not supported through Jedis");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearchStore(byte[], byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long geoSearchStore(byte[] destKey, byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
throw new UnsupportedOperationException("GEOSEARCHSTORE not supported through Jedis");
|
||||
}
|
||||
|
||||
private DataAccessException convertJedisAccessException(Exception ex) {
|
||||
return connection.convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,6 @@ class JedisGeoCommands implements RedisGeoCommands {
|
||||
Assert.notNull(members, "Members must not be null!");
|
||||
Assert.noNullElements(members, "Members must not contain null!");
|
||||
|
||||
|
||||
return connection.invoke().fromMany(BinaryJedis::geopos, MultiKeyPipelineBase::geopos, key, members)
|
||||
.toList(JedisConverters::toPoint);
|
||||
}
|
||||
@@ -257,4 +256,24 @@ class JedisGeoCommands implements RedisGeoCommands {
|
||||
public Long geoRemove(byte[] key, byte[]... members) {
|
||||
return connection.zSetCommands().zRem(key, members);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearch(byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoSearch(byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args) {
|
||||
throw new UnsupportedOperationException("GEOSEARCH not supported through Jedis");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearchStore(byte[], byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long geoSearchStore(byte[] destKey, byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
throw new UnsupportedOperationException("GEOSEARCHSTORE not supported through Jedis");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.*;
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoReference.*;
|
||||
|
||||
import io.lettuce.core.*;
|
||||
import io.lettuce.core.cluster.models.partitions.Partitions;
|
||||
import io.lettuce.core.cluster.models.partitions.RedisClusterNode.NodeFlag;
|
||||
@@ -42,9 +45,6 @@ import org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldSub
|
||||
import org.springframework.data.redis.connection.RedisClusterNode.Flag;
|
||||
import org.springframework.data.redis.connection.RedisClusterNode.LinkState;
|
||||
import org.springframework.data.redis.connection.RedisClusterNode.SlotRange;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Direction;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.connection.RedisNode.NodeType;
|
||||
@@ -868,6 +868,17 @@ public abstract class LettuceConverters extends Converters {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static GeoArgs toGeoArgs(GeoRadiusCommandArgs args) {
|
||||
return toGeoArgs((GeoSearchCommandArgs) args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link GeoRadiusCommandArgs} into {@link GeoArgs}.
|
||||
*
|
||||
* @param args
|
||||
* @return
|
||||
* @since 2.6
|
||||
*/
|
||||
public static GeoArgs toGeoArgs(GeoSearchCommandArgs args) {
|
||||
|
||||
GeoArgs geoArgs = new GeoArgs();
|
||||
|
||||
@@ -896,7 +907,35 @@ public abstract class LettuceConverters extends Converters {
|
||||
}
|
||||
|
||||
if (args.hasLimit()) {
|
||||
geoArgs.withCount(args.getLimit());
|
||||
geoArgs.withCount(args.getLimit(), args.hasAnyLimit());
|
||||
}
|
||||
return geoArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link GeoRadiusCommandArgs} into {@link GeoArgs}.
|
||||
*
|
||||
* @param args
|
||||
* @return
|
||||
* @since 2.6
|
||||
*/
|
||||
static GeoArgs toGeoArgs(GeoSearchStoreCommandArgs args) {
|
||||
|
||||
GeoArgs geoArgs = new GeoArgs();
|
||||
|
||||
if (args.hasSortDirection()) {
|
||||
switch (args.getSortDirection()) {
|
||||
case ASC:
|
||||
geoArgs.asc();
|
||||
break;
|
||||
case DESC:
|
||||
geoArgs.desc();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.hasLimit()) {
|
||||
geoArgs.withCount(args.getLimit(), args.hasLimit());
|
||||
}
|
||||
return geoArgs;
|
||||
}
|
||||
@@ -1114,6 +1153,41 @@ public abstract class LettuceConverters extends Converters {
|
||||
return LMoveArgs.Builder.rightRight();
|
||||
}
|
||||
|
||||
static GeoSearch.GeoPredicate toGeoPredicate(GeoShape predicate) {
|
||||
|
||||
if (predicate instanceof RadiusShape) {
|
||||
|
||||
Distance radius = ((RadiusShape) predicate).getRadius();
|
||||
|
||||
return GeoSearch.byRadius(radius.getValue(), toGeoArgsUnit(radius.getMetric()));
|
||||
}
|
||||
|
||||
if (predicate instanceof BoxShape) {
|
||||
|
||||
BoxShape boxPredicate = (BoxShape) predicate;
|
||||
BoundingBox boundingBox = boxPredicate.getBoundingBox();
|
||||
return GeoSearch.byBox(boundingBox.getWidth().getValue(), boundingBox.getHeight().getValue(),
|
||||
toGeoArgsUnit(boxPredicate.getMetric()));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Cannot convert %s to Lettuce GeoPredicate", predicate));
|
||||
}
|
||||
|
||||
static <T> GeoSearch.GeoRef<T> toGeoRef(GeoReference<T> reference) {
|
||||
|
||||
if (reference instanceof GeoSearchMemberReference) {
|
||||
return GeoSearch.fromMember(((GeoSearchMemberReference<T>) reference).getMember());
|
||||
}
|
||||
|
||||
if (reference instanceof GeoSearchCoordinateReference) {
|
||||
|
||||
GeoSearchCoordinateReference<?> coordinates = (GeoSearchCoordinateReference<?>) reference;
|
||||
return GeoSearch.fromCoordinates(coordinates.getLongitude(), coordinates.getLatitude());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Cannot convert %s to Lettuce GeoRef", reference));
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.GeoArgs;
|
||||
import io.lettuce.core.GeoSearch;
|
||||
import io.lettuce.core.GeoWithin;
|
||||
import io.lettuce.core.api.async.RedisGeoAsyncCommands;
|
||||
|
||||
@@ -268,4 +269,46 @@ class LettuceGeoCommands implements RedisGeoCommands {
|
||||
return connection.zSetCommands().zRem(key, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearch(byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<byte[]>> geoSearch(byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(reference, "Reference must not be null!");
|
||||
Assert.notNull(predicate, "GeoPredicate must not be null!");
|
||||
Assert.notNull(args, "GeoSearchCommandArgs must not be null!");
|
||||
|
||||
GeoSearch.GeoRef<byte[]> ref = LettuceConverters.toGeoRef(reference);
|
||||
GeoSearch.GeoPredicate lettucePredicate = LettuceConverters.toGeoPredicate(predicate);
|
||||
GeoArgs geoArgs = LettuceConverters.toGeoArgs(args);
|
||||
|
||||
return connection.invoke().from(RedisGeoAsyncCommands::geosearch, key, ref, lettucePredicate, geoArgs)
|
||||
.get(LettuceConverters.geoRadiusResponseToGeoResultsConverter(predicate.getMetric()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisGeoCommands#geoSearchStore(byte[], byte[], org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long geoSearchStore(byte[] destKey, byte[] key, GeoReference<byte[]> reference, GeoShape predicate,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(reference, "Reference must not be null!");
|
||||
Assert.notNull(predicate, "GeoPredicate must not be null!");
|
||||
Assert.notNull(args, "GeoSearchCommandArgs must not be null!");
|
||||
|
||||
GeoSearch.GeoRef<byte[]> ref = LettuceConverters.toGeoRef(reference);
|
||||
GeoSearch.GeoPredicate lettucePredicate = LettuceConverters.toGeoPredicate(predicate);
|
||||
GeoArgs geoArgs = LettuceConverters.toGeoArgs(args);
|
||||
|
||||
return connection.invoke().just(
|
||||
connection -> connection.geosearchstore(destKey, key, ref, lettucePredicate, geoArgs, args.isStoreDistance()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.GeoArgs;
|
||||
import io.lettuce.core.GeoCoordinates;
|
||||
import io.lettuce.core.GeoSearch;
|
||||
import io.lettuce.core.GeoWithin;
|
||||
import io.lettuce.core.Value;
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -205,6 +206,60 @@ class LettuceReactiveGeoCommands implements ReactiveGeoCommands {
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveGeoCommands#geoSearch(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<GeoSearchCommand, Flux<GeoResult<GeoLocation<ByteBuffer>>>>> geoSearch(
|
||||
Publisher<GeoSearchCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
Assert.notNull(command.getReference(), "GeoReference must not be null!");
|
||||
Assert.notNull(command.getShape(), "GeoShape must not be null!");
|
||||
Assert.notNull(command.getArgs(), "Command args must not be null!");
|
||||
|
||||
GeoArgs geoArgs = command.getArgs().map(LettuceConverters::toGeoArgs).orElseGet(GeoArgs::new);
|
||||
GeoSearch.GeoRef<ByteBuffer> ref = LettuceConverters.toGeoRef(command.getReference());
|
||||
GeoSearch.GeoPredicate predicate = LettuceConverters.toGeoPredicate(command.getShape());
|
||||
|
||||
Flux<GeoResult<GeoLocation<ByteBuffer>>> result = cmd.geosearch(command.getKey(), ref, predicate, geoArgs)
|
||||
.map(converter(command.getShape().getMetric())::convert);
|
||||
|
||||
return new CommandResponse<>(command, result);
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveGeoCommands#geoSearchStore(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<GeoSearchStoreCommand, Long>> geoSearchStore(Publisher<GeoSearchStoreCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).flatMap(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
Assert.notNull(command.getDestKey(), "Destination key must not be null!");
|
||||
Assert.notNull(command.getReference(), "GeoReference must not be null!");
|
||||
Assert.notNull(command.getShape(), "GeoShape must not be null!");
|
||||
Assert.notNull(command.getArgs(), "Command args must not be null!");
|
||||
|
||||
GeoArgs geoArgs = command.getArgs().map(LettuceConverters::toGeoArgs).orElseGet(GeoArgs::new);
|
||||
Boolean storeDist = command.getArgs().map(RedisGeoCommands.GeoSearchStoreCommandArgs::isStoreDistance)
|
||||
.orElse(false);
|
||||
GeoSearch.GeoRef<ByteBuffer> ref = LettuceConverters.toGeoRef(command.getReference());
|
||||
GeoSearch.GeoPredicate predicate = LettuceConverters.toGeoPredicate(command.getShape());
|
||||
|
||||
Mono<Long> result = cmd.geosearchstore(command.getDestKey(), command.getKey(), ref, predicate, geoArgs,
|
||||
storeDist);
|
||||
|
||||
return result.map(it -> new NumericResponse<>(command, it));
|
||||
}));
|
||||
}
|
||||
|
||||
private Converter<GeoWithin<ByteBuffer>, GeoResult<GeoLocation<ByteBuffer>>> converter(Metric metric) {
|
||||
|
||||
return (source) -> {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -23,8 +25,7 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -297,6 +298,8 @@ public interface BoundGeoOperations<K, M> extends BoundKeyOperations<K> {
|
||||
return radius(within, args);
|
||||
}
|
||||
|
||||
// TODO: Bound ops should not accept K key
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the circle defined by the {@literal members} coordinates and given
|
||||
* {@literal radius}.
|
||||
@@ -408,4 +411,191 @@ public interface BoundGeoOperations<K, M> extends BoundKeyOperations<K> {
|
||||
default Long geoRemove(M... members) {
|
||||
return remove(members);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the boundaries of a given {@link Circle}.
|
||||
*
|
||||
* @param within must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(Circle within) {
|
||||
return search(GeoReference.fromCircle(within), GeoShape.byRadius(within.getRadius()),
|
||||
GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(RedisGeoCommands.GeoReference<M> reference, Distance radius) {
|
||||
return search(reference, radius, GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(RedisGeoCommands.GeoReference<M> reference, Distance radius,
|
||||
GeoSearchCommandArgs args) {
|
||||
return search(reference, GeoShape.byRadius(radius), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox) {
|
||||
return search(reference, boundingBox, GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox,
|
||||
GeoSearchCommandArgs args) {
|
||||
return search(reference, GeoShape.byBox(boundingBox), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link GeoShape predicate} applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param geoPredicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
GeoResults<GeoLocation<M>> search(RedisGeoCommands.GeoReference<M> reference, GeoShape geoPredicate,
|
||||
GeoSearchCommandArgs args);
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the boundaries of a given {@link Circle} and store results at {@code destKey}.
|
||||
*
|
||||
* @param within must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K destKey, Circle within) {
|
||||
return searchAndStore(destKey, GeoReference.fromCircle(within), GeoShape.byRadius(within.getRadius()),
|
||||
GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} and store results at {@code destKey}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K destKey, RedisGeoCommands.GeoReference<M> reference, Distance radius) {
|
||||
return searchAndStore(destKey, reference, radius, GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K destKey, RedisGeoCommands.GeoReference<M> reference, Distance radius,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return searchAndStore(destKey, reference, GeoShape.byRadius(radius), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box and store results at {@code destKey}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K destKey, RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox) {
|
||||
return searchAndStore(destKey, reference, boundingBox, GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K destKey, RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return searchAndStore(destKey, reference, GeoShape.byBox(boundingBox), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link GeoShape predicate} applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param geoPredicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long searchAndStore(K destKey, RedisGeoCommands.GeoReference<M> reference, GeoShape geoPredicate,
|
||||
GeoSearchStoreCommandArgs args);
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
|
||||
@@ -177,6 +178,26 @@ class DefaultBoundGeoOperations<K, M> extends DefaultBoundKeyOperations<K> imple
|
||||
return ops.remove(getKey(), members);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundGeoOperations#search(org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<M>> search(RedisGeoCommands.GeoReference<M> reference,
|
||||
RedisGeoCommands.GeoShape geoPredicate, RedisGeoCommands.GeoSearchCommandArgs args) {
|
||||
return ops.search(getKey(), reference, geoPredicate, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundGeoOperations#searchAndStore(java.lang.Object, org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long searchAndStore(K destKey, RedisGeoCommands.GeoReference<M> reference,
|
||||
RedisGeoCommands.GeoShape geoPredicate, RedisGeoCommands.GeoSearchStoreCommandArgs args) {
|
||||
return ops.searchAndStore(getKey(), destKey, reference, geoPredicate, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundKeyOperations#getType()
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
|
||||
@@ -241,4 +242,44 @@ class DefaultGeoOperations<K, M> extends AbstractOperations<K, M> implements Geo
|
||||
byte[][] rawMembers = rawValues(members);
|
||||
return execute(connection -> connection.zRem(rawKey, rawMembers), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.GeoOperations#search(java.lang.Object, org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public GeoResults<GeoLocation<M>> search(K key, RedisGeoCommands.GeoReference<M> reference,
|
||||
RedisGeoCommands.GeoShape geoPredicate, RedisGeoCommands.GeoSearchCommandArgs args) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
RedisGeoCommands.GeoReference<byte[]> rawMember = getGeoReference(reference);
|
||||
|
||||
GeoResults<GeoLocation<byte[]>> raw = execute(
|
||||
connection -> connection.geoSearch(rawKey, rawMember, geoPredicate, args), true);
|
||||
|
||||
return deserializeGeoResults(raw);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.GeoOperations#searchAndStore(java.lang.Object, java.lang.Object, org.springframework.data.redis.connection.RedisGeoCommands.GeoReference, org.springframework.data.redis.connection.RedisGeoCommands.GeoShape, org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference,
|
||||
RedisGeoCommands.GeoShape geoPredicate, RedisGeoCommands.GeoSearchStoreCommandArgs args) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
byte[] rawDestKey = rawKey(destKey);
|
||||
RedisGeoCommands.GeoReference<byte[]> rawMember = getGeoReference(reference);
|
||||
|
||||
return execute(connection -> connection.geoSearchStore(rawDestKey, rawKey, rawMember, geoPredicate, args), true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RedisGeoCommands.GeoReference<byte[]> getGeoReference(RedisGeoCommands.GeoReference<M> reference) {
|
||||
return reference instanceof RedisGeoCommands.GeoReference.GeoSearchMemberReference
|
||||
? RedisGeoCommands.GeoReference
|
||||
.fromMember(rawValue(((RedisGeoCommands.GeoReference.GeoSearchMemberReference<M>) reference).getMember()))
|
||||
: (RedisGeoCommands.GeoReference<byte[]>) reference;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.ReactiveGeoCommands;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
@@ -334,6 +335,38 @@ class DefaultReactiveGeoOperations<K, V> implements ReactiveGeoOperations<K, V>
|
||||
return template.createMono(connection -> connection.keyCommands().del(rawKey(key))).map(l -> l != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveGeoOperations#search(K, RedisGeoCommands.GeoReference, GeoShape, GeoSearchCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Flux<GeoResult<GeoLocation<V>>> search(K key, RedisGeoCommands.GeoReference<V> reference,
|
||||
RedisGeoCommands.GeoShape geoPredicate, RedisGeoCommands.GeoSearchCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(reference, "GeoReference must not be null!");
|
||||
RedisGeoCommands.GeoReference<ByteBuffer> rawReference = getGeoReference(reference);
|
||||
|
||||
return template.createFlux(connection -> connection.geoCommands()
|
||||
.geoSearch(rawKey(key), rawReference, geoPredicate, args).map(this::readGeoResult));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveGeoOperations#searchAndStore(K, K, RedisGeoCommands.GeoReference, GeoShape, GeoSearchStoreCommandArgs)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<V> reference,
|
||||
RedisGeoCommands.GeoShape geoPredicate, RedisGeoCommands.GeoSearchStoreCommandArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(reference, "GeoReference must not be null!");
|
||||
RedisGeoCommands.GeoReference<ByteBuffer> rawReference = getGeoReference(reference);
|
||||
|
||||
return template.createMono(connection -> connection.geoCommands().geoSearchStore(rawKey(destKey), rawKey(key),
|
||||
rawReference, geoPredicate, args));
|
||||
}
|
||||
|
||||
private <T> Mono<T> createMono(Function<ReactiveGeoCommands, Publisher<T>> function) {
|
||||
|
||||
Assert.notNull(function, "Function must not be null!");
|
||||
@@ -348,6 +381,14 @@ class DefaultReactiveGeoOperations<K, V> implements ReactiveGeoOperations<K, V>
|
||||
return template.createFlux(connection -> function.apply(connection.geoCommands()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RedisGeoCommands.GeoReference<ByteBuffer> getGeoReference(RedisGeoCommands.GeoReference<V> reference) {
|
||||
return reference instanceof RedisGeoCommands.GeoReference.GeoSearchMemberReference
|
||||
? RedisGeoCommands.GeoReference
|
||||
.fromMember(rawValue(((RedisGeoCommands.GeoReference.GeoSearchMemberReference<V>) reference).getMember()))
|
||||
: (RedisGeoCommands.GeoReference<ByteBuffer>) reference;
|
||||
}
|
||||
|
||||
private ByteBuffer rawKey(K key) {
|
||||
return serializationContext.getKeySerializationPair().write(key);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -23,8 +25,8 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.*;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -437,4 +439,204 @@ public interface GeoOperations<K, M> {
|
||||
default Long geoRemove(K key, M... members) {
|
||||
return remove(key, members);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the boundaries of a given {@link Circle}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param within must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(K key, Circle within) {
|
||||
return search(key, GeoReference.fromCircle(within), GeoShape.byRadius(within.getRadius()),
|
||||
GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(K key, RedisGeoCommands.GeoReference<M> reference, Distance radius) {
|
||||
return search(key, reference, radius, GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(K key, RedisGeoCommands.GeoReference<M> reference, Distance radius,
|
||||
GeoSearchCommandArgs args) {
|
||||
return search(key, reference, GeoShape.byRadius(radius), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(K key, RedisGeoCommands.GeoReference<M> reference,
|
||||
BoundingBox boundingBox) {
|
||||
return search(key, reference, boundingBox, GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
default GeoResults<GeoLocation<M>> search(K key, RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox,
|
||||
GeoSearchCommandArgs args) {
|
||||
return search(key, reference, GeoShape.byBox(boundingBox), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link GeoShape predicate} applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param geoPredicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
@Nullable
|
||||
GeoResults<GeoLocation<M>> search(K key, RedisGeoCommands.GeoReference<M> reference,
|
||||
GeoShape geoPredicate, GeoSearchCommandArgs args);
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the boundaries of a given {@link Circle} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param within must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K key, K destKey, Circle within) {
|
||||
return searchAndStore(key, destKey, GeoReference.fromCircle(within), GeoShape.byRadius(within.getRadius()),
|
||||
GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, Distance radius) {
|
||||
return searchAndStore(key, destKey, reference, radius, GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, Distance radius,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return searchAndStore(key, destKey, reference, GeoShape.byRadius(radius), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox) {
|
||||
return searchAndStore(key, destKey, reference, boundingBox, GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Long searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, BoundingBox boundingBox,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return searchAndStore(key, destKey, reference, GeoShape.byBox(boundingBox), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link GeoShape predicate} applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param geoPredicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return never {@literal null} unless used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, GeoShape geoPredicate,
|
||||
GeoSearchStoreCommandArgs args);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.springframework.data.redis.connection.RedisGeoCommands.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -23,13 +25,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import org.springframework.data.geo.Circle;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
|
||||
/**
|
||||
* Reactive Redis operations for geo commands.
|
||||
@@ -228,4 +230,193 @@ public interface ReactiveGeoOperations<K, M> {
|
||||
* @param key must not be {@literal null}.
|
||||
*/
|
||||
Mono<Boolean> delete(K key);
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the boundaries of a given {@link Circle}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param within must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Flux<GeoResult<GeoLocation<M>>> search(K key, Circle within) {
|
||||
return search(key, GeoReference.fromCircle(within), GeoShape.byRadius(within.getRadius()),
|
||||
GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Flux<GeoResult<GeoLocation<M>>> search(K key, RedisGeoCommands.GeoReference<M> reference, Distance radius) {
|
||||
return search(key, reference, radius, GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Flux<GeoResult<GeoLocation<M>>> search(K key, RedisGeoCommands.GeoReference<M> reference, Distance radius,
|
||||
GeoSearchCommandArgs args) {
|
||||
return search(key, reference, GeoShape.byRadius(radius), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Flux<GeoResult<GeoLocation<M>>> search(K key, RedisGeoCommands.GeoReference<M> reference,
|
||||
BoundingBox boundingBox) {
|
||||
return search(key, reference, boundingBox, GeoSearchCommandArgs.newGeoSearchArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
default Flux<GeoResult<GeoLocation<M>>> search(K key, RedisGeoCommands.GeoReference<M> reference,
|
||||
BoundingBox boundingBox, GeoSearchCommandArgs args) {
|
||||
return search(key, reference, GeoShape.byBox(boundingBox), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link GeoShape predicate} applying {@link GeoRadiusCommandArgs}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param geoPredicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearch">Redis Documentation: GEOSEARCH</a>
|
||||
*/
|
||||
Flux<GeoResult<GeoLocation<M>>> search(K key, RedisGeoCommands.GeoReference<M> reference, GeoShape geoPredicate,
|
||||
GeoSearchCommandArgs args);
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s within the boundaries of a given {@link Circle} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param within must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
default Mono<Long> searchAndStore(K key, K destKey, Circle within) {
|
||||
return searchAndStore(key, destKey, GeoReference.fromCircle(within), GeoShape.byRadius(within.getRadius()),
|
||||
GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
default Mono<Long> searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, Distance radius) {
|
||||
return searchAndStore(key, destKey, reference, radius, GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link Distance radius} applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param radius must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
default Mono<Long> searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, Distance radius,
|
||||
GeoSearchStoreCommandArgs args) {
|
||||
return searchAndStore(key, destKey, reference, GeoShape.byRadius(radius), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
default Mono<Long> searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference,
|
||||
BoundingBox boundingBox) {
|
||||
return searchAndStore(key, destKey, reference, boundingBox, GeoSearchStoreCommandArgs.newGeoSearchStoreArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* bounding box applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param boundingBox must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
default Mono<Long> searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference,
|
||||
BoundingBox boundingBox, GeoSearchStoreCommandArgs args) {
|
||||
return searchAndStore(key, destKey, reference, GeoShape.byBox(boundingBox), args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@literal member}s using {@link GeoReference} as center of the query within the boundaries of a given
|
||||
* {@link GeoShape predicate} applying {@link GeoRadiusCommandArgs} and store results at {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @param geoPredicate must not be {@literal null}.
|
||||
* @param args must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/geosearchstore">Redis Documentation: GEOSEARCHSTORE</a>
|
||||
*/
|
||||
Mono<Long> searchAndStore(K key, K destKey, RedisGeoCommands.GeoReference<M> reference, GeoShape geoPredicate,
|
||||
GeoSearchStoreCommandArgs args);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user