Search Algorithm Implementation for nearby persons

Source: Internet
Author: User

With the popularization of mobile terminals, many applications are based on the LBS function, near XX (restaurants, banks, sister paper, etc ).

In basic data, the longitude and latitude of the target location are generally stored. the longitude and latitude provided by the user are used for comparison to determine whether the target location is nearby.

Objectives:

Search for the nearby XXX and return the result from near to far. The result contains the distance from the target point.

For nearby XXX search, the solution is as follows:

Geohash algorithm; geohash is an address encoding algorithm that encodes two-dimensional longitude and latitude into one-dimensional strings.

The following is an example:

For example, the Code for Chengdu Yongfeng interchange is wm3yr31d2524.

Advantages:

1. Use a field to store the longitude and latitude. Only one index is required for search, which is highly efficient.

2. the prefix of the encoding can represent a larger area. It is very convenient to find nearby areas. In SQL, like 'wm3yr3% 'to query all nearby locations.

3. Fuzzy coordinates and privacy protection can be achieved through encoding accuracy.

Disadvantage: the distance and sorting operations must be performed twice (the filtering results are running very fast)

The specific algorithm steps are as follows:

1. geohash Encoding Algorithm

Longitude and latitude of Chengdu Yongfeng Interchange (30.63578, 104.031601)

1.1. The latitude range (-90, 90) is divided into two intervals (-90, 0) and (0, 90). If the target latitude is located in the first interval, It is encoded as 0, otherwise, the code is 1.

Because 30.625265 belongs to (0, 90), the encoding is 1.

Then divide (0, 90) into (0, 45), (45, 90) two intervals, and 39.92324 is located in (0, 45), so the encoding is 0,

Then divide (0, 45) into (0, 22.5), (22.5, 45) two intervals, and 39.92324 is located in (22.5, 45), so the code is 1,

Similarly, the Yongfeng interchange latitude code is 101010111001001000100101101010.

1.2. The longitude is subdivided by (-180,180) using the same algorithm. (-180,180) and (110010011111101001100000000000) are encoded.

1.3. Merge the latitude and longitude codes. from high to low, take one longitude first, and then one latitude. The result is 111001001100011111101011100011000010110000010001010001000100.

1.4. Use the 32 Letters 0-9 and B-z (remove a, I, L, O) for base32 encoding, and the code (30.63578, 104.031601) is wm3yr31d2524.

11100 10011 00011 11110 10111 00011 00001 01100 00010 00101 00010 => wm3yr31d2524

Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Base32 0 1 2 3 4 5 6 7 8 9 B c d E F G

Decimal 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

Base32 h j k m n p q r s t u v w x Y Z

2. Specific matching policy

1. When the latitude and longitude are stored in the database, a new geohash field is added to the database to record the geohash value of this point.

2. Search nearby and use like 'wm3yr3% 'in the SQL statement. The result can be cached. in the residential area, the database query is not performed because the latitude and longitude are changed.

3. If you need to specify the distance or sort, you can use the distance formula and two-dimensional data to sort the results. In this case, a small amount of data will be generated quickly.

Import Java. util. hashmap; import Java. util. map; public class geohashkit {Private Static char [] base32 = {'0', '1', '2', '3', '4', '5 ', '6', '7', '8', '9', 'B', 'C', 'D', 'E', 'F', 'G ', 'H', 'J', 'k', 'M', 'n', 'P', 'Q', 'R', 's','t ', 'U', 'V', 'w', 'x', 'y', 'z'}; private final static Map <character, integer> decodemap = new hashmap <character, integer> (); static {int SZ = base32.length; For (INT I = 0; I <SZ; I ++) {decodemap. put (base32 [I], I) ;}} Private Static int precision = 10; Private Static int [] bits = {16, 8, 4, 2, 1 }; /*** set precision ** @ Param int precision sets the exact number of digits. This parameter determines the longitude of the algorithm ***/public static void setprecision (INT precision) {geohashkit. precision = precision;} public static double getprecision (Double X, Double Precision) {double base = math. pow (10,-precision); double diff = x % base; Return X-diff;} public static string encode (double latitude, double longpolling) {double [] lat_interval = {-90.0, 90.0}; double [] lon_interval = {-180.0, 180.0}; stringbuilder geohash = new stringbuilder (); Boolean is_even = true; int bit = 0, CH = 0; while (geohash. length () <precision) {double mid = 0.0; If (is_even) {mid = (lon_interval [0] + lon_interval [1])/2; If (longpolling> mid) {ch | = bits [bit]; lon _ Interval [0] = mid;} else {lon_interval [1] = mid;} else {mid = (lat_interval [0] + lat_interval [1])/2; if (latitude> mid) {ch | = bits [bit]; lat_interval [0] = mid;} else {lat_interval [1] = mid ;}} is_even = is_even? False: true; If (bit <4) {bit ++;} else {geohash. append (base32 [CH]); bit = 0; CH = 0 ;}} return geohash. tostring ();} public static double [] Decode (string geohash) {double [] Ge = decode_exactly (geohash); double Lat, Lon, lat_err, lon_err; lat = Ge [0]; Lon = Ge [1]; lat_err = Ge [2]; lon_err = Ge [3]; double lat_precision = math. max (1, math. round (-math. log10 (lat_err)-1; double lon_precision = math. max (1, math. Round (-math. log10 (lon_err)-1; lat = getprecision (Lat, lat_precision); Lon = getprecision (Lon, lon_precision); return New Double [] {Lat, Lon };} public static double [] decode_exactly (string geohash) {double [] lat_interval = {-90.0, 90.0}; double [] lon_interval = {-180.0, 180.0}; double lat_err = 90.0; double lon_err = 180.0; Boolean is_even = true; int SZ = geohash. length (); int bsz = bits. length; do Uble latitude, longpolling; For (INT I = 0; I <SZ; I ++) {int Cd = decodemap. get (geohash. charat (I); For (INT z = 0; Z <bsz; Z ++) {int mask = bits [Z]; If (is_even) {lon_err/= 2; if (CD & Mask )! = 0) {lon_interval [0] = (lon_interval [0] + lon_interval [1])/2 ;} else {lon_interval [1] = (lon_interval [0] + lon_interval [1])/2 ;}} else {lat_err/= 2; If (CD & Mask )! = 0) {lat_interval [0] = (lat_interval [0] + lat_interval [1])/2 ;} else {lat_interval [1] = (lat_interval [0] + lat_interval [1])/2 ;}} is_even = is_even? False: True ;}} latitude = (lat_interval [0] + lat_interval [1])/2; longpolling = (lon_interval [0] + lon_interval [1])/2; return New Double [] {latitude, longpolling, lat_err, lon_err };} public static void main (string [] ARGs) {geohashkit ghf = new geohashkit (); string gc1 = ghf. encode (31.277631, 120.53916300000003); string GC2 = ghf. encode (51.4797,-0.0124); system. out. println (gc1); system. out. println (GC2); double [] gd1 = ghf. decode (gc1); double [] GD2 = ghf. decode (GC2); system. out. println (gd1 [0] + "," + gd1 [1]); system. out. println (GD2 [0] + "," + GD2 [1]) ;}}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.