20 Look Up Nearby People With Geo

20 Look Up Nearby People with GEO #

As educated individuals, we all know that any location can be identified by its longitude and latitude. The range of longitudes is -180 to 180, and the range of latitudes is -90 to 90. Latitudes are negative south of the equator and positive north of the equator, while longitudes are positive east of the prime meridian (Greenwich, United Kingdom) and negative west of the prime meridian.

Redis introduced the GEO type in version 3.2 for storing and querying geographical locations. There are only a few commands related to GEO, mainly including the following 6:

  1. geoadd: Add a geographical location
  2. geopos: Query location information
  3. geodist: Distance calculation
  4. georadius: Query other member information within a specified location
  5. geohash: Query hash value of a location
  6. zrem: Delete a geographical location

Now let’s take a look at how to use these commands.

Basics #

Add a geographical location #

First, let’s use the latitude and longitude query tool provided by Baidu Maps, using the following address:

http://api.map.baidu.com/lbsapi/getpoint/index.html

Here is a screenshot of the tool:

Baidu Maps Latitude and Longitude Query Tool.png

Let’s add the following 4 locations to Redis:

  1. Tiananmen Square: 116.404269, 39.913164
  2. Yuetan Park: 116.36, 39.922461
  3. Beijing Happy Valley: 116.499705, 39.874635
  4. Fragrant Hills Park: 116.193275, 39.996348

Here’s the code:

127.0.0.1:6379> geoadd site 116.404269 39.913164 tianan
(integer) 1
127.0.0.1:6379> geoadd site 116.36 39.922461 yuetan
(integer) 1
127.0.0.1:6379> geoadd site 116.499705 39.874635 huanle
(integer) 1
127.0.0.1:6379> geoadd site 116.193275 39.996348 xiangshan
(integer) 1

The syntax is as follows:

geoadd key longitude latitude member [longitude latitude member ...]

Here are some important parameter explanations:

  • longitude: The longitude coordinate
  • latitude: The latitude coordinate
  • member: The name for this coordinate

This command supports adding one or multiple location information at once.

Query location information #

127.0.0.1:6379> geopos site tianan
1) 1) "116.40541702508926392"
   2) "39.91316289865137179"

The syntax is as follows:

geopos key member [member ...]

This command supports querying one or multiple location information.

Distance calculation #

127.0.0.1:6379> geodist site tianan yuetan km
"3.9153"

We can see that the straight-line distance between Tiananmen Square and Yuetan Park is approximately 3.9 km. Let’s open a map tool to test the accuracy of our calculation. Here is an example:

Distance Calculation from Tiananmen Square to Yuetan Park.png

We can see that Redis’ calculation matches perfectly with the result from the map tool.

Note: This command calculates the straight-line distance between two locations.

The syntax is as follows:

geodist key member1 member2 [unit]

The unit parameter represents the unit of distance and can take the following values:

  • m: meters (default)
  • km: kilometers
  • mi: miles
  • ft: feet

Query other member information within a specified location #

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km
1) "tianan"
2) "yuetan"

This command queries the members within a 5 km radius from the location of Tiananmen Square (116.405419, 39.913164).

The syntax is as follows:

georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]

Here are some optional parameters:

1. WITHCOORD

Explanation: Returns the longitude and latitude coordinates of the matching locations.

Example code:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withcoord
1) 1) "tianan"
   2) 1) "116.40426903963088989"
      2) "39.91316289865137179"
2) 1) "yuetan"
   2) 1) "116.36000186204910278"
      2) "39.92246025586381819"

2. WITHDIST

Explanation: Returns the straight-line distance between the matching locations and the queried location. Example code:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withdist
1) 1) "tianan"
   2) "0.0981"
2) 1) "yuetan"
   2) "4.0100"

3. WITHHASH

Description: Returns the hash of the positions that satisfy the conditions.

Example code:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withhash
1) 1) "tianan"
   2) (integer) 4069885552230465
2) 1) "yuetan"
   2) (integer) 4069879797297521

4. COUNT count

Description: Specifies the number of positions that satisfy the conditions to be returned.

For example, to return only one position that satisfies the conditions, use the following code:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km count 1
1) "tianan"

5. ASC|DESC

Description: Returns the positions in ascending or descending order.

Example code:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km desc
1) "yuetan"
2) "tianan"
127.0.0.1:6379> georadius site 116.405419 39.913164 5 km asc
1) "tianan"
2) "yuetan"

Of course, these optional parameters can also be used together. For example, the following code:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withdist desc
1) 1) "yuetan"
   2) "4.0100"
2) 1) "tianan"
   2) "0.0981"

5. Query hash value

127.0.0.1:6379> geohash site tianan
1) "wx4g0cgp000"

Syntax:

geohash key member [member ...]

This command supports querying the hash value of one or more addresses.

6. Delete geographical position

127.0.0.1:6379> zrem site xiaoming
(integer) 1

Syntax:

zrem key member [member ...]

This command supports deleting one or more location information.

Practical examples #

Now let’s use Java code to implement the query of nearby people. The complete code is as follows:

import redis.clients.jedis.GeoCoordinate;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GeoHashExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        Map<String, GeoCoordinate> map = new HashMap<>();
        // Add Xiaoming's location
        map.put("xiaoming", new GeoCoordinate(116.404269, 39.913164));
        // Add Xiaohong's location
        map.put("xiaohong", new GeoCoordinate(116.36, 39.922461));
        // Add Xiaomei's location
        map.put("xiaomei", new GeoCoordinate(116.499705, 39.874635));
        // Add Xiaoer
        map.put("xiaoer", new GeoCoordinate(116.193275, 39.996348));
        jedis.geoadd("person", map);
        // Query the straight-line distance between Xiaoming and Xiaohong
        System.out.println("Distance between Xiaoming and Xiaohong: " + jedis.geodist("person", "xiaoming",
                "xiaohong", GeoUnit.KM) + " KM");
        // Query people within 5 kilometers of Xiaoming
        List<GeoRadiusResponse> res = jedis.georadiusByMemberReadonly("person", "xiaoming",
                5, GeoUnit.KM);
        for (int i = 1; i < res.size(); i++) {
            System.out.println("Person near Xiaoming: " + res.get(i).getMemberByString());
        }
    }
}

The result of executing the above program is as follows:

Distance between Xiaoming and Xiaohong: 3.9153 KM
Person near Xiaoming: xiaohong

Applications #

The classic use cases of GEO in Redis are as follows:

  1. Query nearby people or places;
  2. Calculate related distance information.

Summary #

GEO is a new feature added in Redis 3.2. It can only be used if you upgrade to 3.2+. GEO is essentially implemented based on ZSet, which can be used to find nearby people or places and calculate the straight-line distance between two locations.