preface

“Like” is a habit.

Click like collection, brilliant life.

Click on [wechat search public number: Programming back pot man] to prevent getting lost.

Usage scenarios

The most common geographic distance sorting algorithm in the industry is the GeoHash algorithm, which is also used by Redis. For example, our delivery man needs to locate the distance of the location to be delivered. For example, when we are looking for a job, we need to find out where the company is and how far it is. As well as we are inquiring about the nearby shared bikes 🚴♀️ how many kilometers are the nearest.

Contents summary

methods An overview of the
Long add(K key, Point point, M member); Add elements
List hash(K key, M… members); Gets a hash of a geographic location
List position(K key, M… members); Get geolocation data based on keys and elements
Distance distance(K key, M member1, M member1, Metric metric); Calculates the distance between two elements
GeoResults<GeoLocation> radius(K key, M member, Distance distance, GeoRadiusCommandArgs args); Queries other elements near the specified element
GeoResults<GeoLocation> radius(K key, Circle within, GeoRadiusCommandArgs args); Query other elements near the specified element – overload method

Redis in the Geo command basic use

Add latitude and longitude element command

127.0.0.1:6379> geoadd location 116.307629 40.058359 baidu
(integer1)Copy the code

Get the hash value command

127.0.0.1:6379 > geohash location baidu1) "wx4eysksu50"
Copy the code

Gets the geolocation command

127.0.0.1:6379 > geopos location baidu1) 1) "116.3076290488243103"
   2) "40.05835933082178002"
Copy the code

Computes the distance between two elements

127.0.0.1:6379> Baidu Meituan km"16.4455"
Copy the code

Queries other element commands near the specified element

# withdist it can be used to show distance
# asc sorting
# count 3 Prints several pieces of data
127.0.0.1:6379> GEORADIUSBYMEMBER location baidu 20 km withcoord withdist withhash count 3 ASC1) 1) "baidu"
 2) "0.0000" (3)integer) 4069883733203026  4) 1) "116.3076290488243103"  2) "40.05835933082178002" 2) 1) "xiaomi"  2) "4.1227" (3)integer) 4069880904286516  4) 1) "116.33425265550613403"  2) "40.02740024658161389" 3) 1) "juejin"  2) "16.2804" (3)integer) 4069887154388167  4) 1) "116.48104995489120483"  2) "39.99679348858259686" Copy the code

Redis Geo is used in the code

Add some latitude and longitude data to the Reids

The source code interpretation

// Add the specified element to redis based on the specified key. Key: key of redis,point: object that encapsulates latitude and longitude,member: element
@Nullable
Long add(K key, Point point, M member);
Copy the code

Case presentation

/ * ** Initialization data for geographic locations* /
@Test
public void test_user_simple_geohash_init(a){
 String key = "location";  stringRedisTemplate.opsForGeo().add(key, new Point(116.48105.39.996794), "juejin");  stringRedisTemplate.opsForGeo().add(key, new Point(116.514203.39.905409), "ireader");  stringRedisTemplate.opsForGeo().add(key, new Point(116.489033.40.007669), "meituan");  stringRedisTemplate.opsForGeo().add(key, new Point(116.562108.39.787602), "jd");  stringRedisTemplate.opsForGeo().add(key, new Point(116.334255.40.027400), "xiaomi"); } Copy the code

Gets a hash of a geographic location

The source code interpretation

// Gets the hash value of the element in the specified key. Key: the specified key, members: the element from which the hash value is to be obtained
@Nullable
List<String> hash(K key, M... members);
Copy the code

Case presentation

/ * ** Get the hash value of the geographic location* /
@Test
public void test_user_simple_geohash_hash(a){
 String key = "location";  List<String> position = stringRedisTemplate.opsForGeo().hash(key, "juejin"."ireader"."meituan"."jd"."xiaomi");  assertposition ! =null;  position.forEach(System.out::println); } Copy the code

Print the result

wx4gd94yjn0
wx4g52e1ce0
wx4gdg0tx40
wx4fk7jgtf0
wx4exqb0880
Copy the code

Get geolocation data based on keys and elements

The source code interpretation

// Get geolocation data based on key and element. Key: specifies the key. Members: specifies the element
@Nullable
List<Point> position(K key, M... members);
Copy the code

Case presentation

/ * ** Get geo-location data* /
@Test
public void test_user_simple_geohash_get(a){
 String key = "location";  // Get more than one at a time or one at a time  List<Point> position = stringRedisTemplate.opsForGeo().position(key, "juejin"."ireader"."meituan"."jd"."xiaomi");  assertposition ! =null;  position.forEach(System.out::println); } Copy the code

Print the result

Point [x=116.481050, y=39.996793]
Point [x=116.514202, y=39.905409]
Point [x=116.489032, y=40.007670]
Point [x=116.562106, y=39.787603]
Point [x=116.334253, y=40.027400]
Copy the code

Calculates the distance between two elements

The source code interpretation

// Calculate the distance between two elements. Key: the specified key, is | are: two elements, Metric: the measuring unit, meters, kilometers...
@Nullable
distancedistance(K key, M member1, M member1, Metric metric);
Copy the code

Case presentation

/ * ** Calculates the distance between two elements* /
@Test
public void test_user_simple_geohash_distance(a){
 String key = "location";  Distance distance = stringRedisTemplate.opsForGeo().distance(key, "juejin"."ireader", RedisGeoCommands.DistanceUnit.KILOMETERS);  assertdistance ! =null;  System.out.println(distance.getValue() + " KM"); } Copy the code

Print the result

10.5501 KM
Copy the code

Queries other elements near the specified element

The source code interpretation

// Query other elements near the specified element, specify the range query, this query will return itself
@Nullable
GeoResults<GeoLocation<M>> radius(K key, M member, Distance distance, GeoRadiusCommandArgs args);
Copy the code

Case presentation

/ * ** Queries other elements near the specified element* /
@Test
public void test_user_simple_geohash_radius(a){
 String key = "location";  // Obtain companies within 3km from the excavation, range search, positive order  RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()  .sortAscending()/ / sorting  .limit(2)// Output the number of elements  .includeCoordinates()// Output latitude and longitude  .includeDistance();/ / distance  // Encapsulate the distance parameter  Distance distance = new Distance(3d, RedisGeoCommands.DistanceUnit.KILOMETERS);  / / get the value  GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringRedisTemplate.opsForGeo().radius(key, "juejin", distance, geoRadiusCommandArgs);  assertradius ! =null;  radius.getContent().forEach(s -> System.out.println("Name:" + s.getContent().getName() + "\n Latitude and longitude:" + s.getContent().getPoint() + "\n Distance:" + s.getDistance())); } Copy the code

Print the result

Name: juejinLatitude and longitude: Point [x=116.481050, y=39.996793]
Distance:0.0 KILOMETERS
Name: at meituanLatitude and longitude: Point [x=116.489032, y=40.007670]
Distance:1.3878 KILOMETERS Copy the code

Query other elements near the specified element – overload method

The source code interpretation

// An overloaded method of the above method
@Nullable
GeoResults<GeoLocation<M>> radius(K key, Circle within, GeoRadiusCommandArgs args);
Copy the code

Case presentation

/ * ** Todo overloaded methods* Queries other elements near the specified element* /
@Test
public void test_user_simple_geohash_radius_circle(a) {  String key = "location";  // Obtain companies within 3km from the excavation, range search, positive order  RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()  .sortAscending()/ / sorting  .limit(2)// Output the number of elements  .includeCoordinates()// Output latitude and longitude  .includeDistance();/ / distance  // Encapsulate the distance parameter  Distance distance = new Distance(3d, RedisGeoCommands.DistanceUnit.KILOMETERS);  // Encapsulate latitude and longitude parameters  Point point = new Point(116.48105.39.996794);  // Encapsulate range parameters  Circle circle = new Circle(point, distance);  GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringRedisTemplate.opsForGeo().radius(key, circle, geoRadiusCommandArgs);  assertradius ! =null;  // The distance obtained may be the result of scientific notation  radius.getContent().forEach(s -> System.out.println("Name:" + s.getContent().getName() + "\n Latitude and longitude:" + s.getContent().getPoint() + "\n Distance:" + s.getDistance())); } Copy the code

Print the result

Name: juejinLatitude and longitude: Point [x=116.481050, y=39.996793]
Distance:1.0 e-4 KILOMETERS
Name: at meituanLatitude and longitude: Point [x=116.489032, y=40.007670]
Distance:1.3878 KILOMETERS Copy the code

Pay attention to

In a map application, the data of cars, restaurants, and people may be in millions and millions, and if Redis's Geo data structure is used, they will all be in one Zset set. In the cluster environment of Redis, the set may be migrated from one node to another. If the data of a single key is too large, the migration of the cluster will be greatly affected. In the cluster environment, the data amount corresponding to a single key should not exceed 1M, otherwise the cluster migration will lag. The online services are affected.Therefore, it is recommended that Geo data be deployed in a separate Redis instance instead of a clustered environment.If the amount of data is over 100 million or even larger, it is necessary to split Geo data by country, by province, by city, and even by district in populous megacities. This can significantly reduce the size of a single Zset collection.Copy the code

Thank you for your thumb up

  • It is not easy to create, and we welcome your likes, comments and concerns
  • Your likes, comments, and followings
  • Is the biggest support and encouragement to me
  • Is my motivation to continue to create high-quality blog!!

This article is formatted using MDNICE