成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

場(chǎng)景解決方案:附近的人(GeoHash的應(yīng)用)

yeyan1996 / 3436人閱讀

摘要:前言附近的人,這四個(gè)字的需求就大有文章可做了。很二逼的做法是,存每個(gè)人的經(jīng)度緯度,然后遍歷數(shù)據(jù)庫(kù)所有數(shù)據(jù)循環(huán),兩點(diǎn)距離坐標(biāo)公式。減少掃描行數(shù)來(lái)實(shí)現(xiàn)減輕數(shù)據(jù)庫(kù)的壓力。兩個(gè)點(diǎn)的距離越近,他們的編碼前綴部分就相同,前綴部分相同越多,代表距離越近。

前言

??附近的人,這四個(gè)字的需求就大有文章可做了。很二逼的做法是,存每個(gè)人的經(jīng)度緯度,然后遍歷數(shù)據(jù)庫(kù)所有數(shù)據(jù),foreach循環(huán),兩點(diǎn)距離坐標(biāo)公式。量少的時(shí)候,這個(gè)沒(méi)啥問(wèn)題。量大了,掃描全表 + 經(jīng)緯度距離運(yùn)算分分鐘拖垮數(shù)據(jù)庫(kù)。那么是否有方案可以解決這個(gè)痛點(diǎn)呢,今年就來(lái)說(shuō)下Geohash

實(shí)現(xiàn)思路

??想要不拖垮數(shù)據(jù),要做到能走索引。就是跟你無(wú)關(guān)的點(diǎn),不要掃描。減少掃描行數(shù)來(lái)實(shí)現(xiàn)減輕數(shù)據(jù)庫(kù)的壓力。那么減少掃描行數(shù)肯定要想到索引。可是經(jīng)緯度有兩個(gè)字段,且查詢條件無(wú)論怎么寫(xiě)都沒(méi)辦法走索引。那么唯一能想到的就是二維變一維。 geohash基本原理是將地球理解為一個(gè)二維平面,將平面遞歸分解成更小的子塊,每個(gè)子塊在一定經(jīng)緯度范圍內(nèi)擁有相同的編碼,這種方式簡(jiǎn)單粗暴,可以滿足對(duì)小規(guī)模的數(shù)據(jù)進(jìn)行經(jīng)緯度的檢索。兩個(gè)點(diǎn)的距離越近,他們的編碼前綴部分就相同,前綴部分相同越多,代表距離越近。然后我們做數(shù)據(jù)庫(kù)掃描的時(shí)候 可以 WHERE geohash Like "code%"這樣就起到了走索引從而優(yōu)化了執(zhí)行效率。

代碼思路(PHP)
 -90, "max" => 90))
    {
        $count   = ($data["max"] - $data["min"]) / 2;
        $limit_0 = array(
            "min" => $data["min"],
            "max" => $data["min"] + $count
        );
        $limit_1 = array(
            "min" => $data["min"] + $count,
            "max" => $data["max"]
        );
        $str     .= $num > $limit_1["min"] ? 1 : 0;
        if ($i >= $max_separate_num) {
            return $str;
        } else {
            return self::separate($num, $str, $i + 1, $max_separate_num, $num > $limit_1["min"] ? $limit_1 : $limit_0);
        }
    }

    /**
     * @param $latitude_str 緯度
     * @param $longitude_str 經(jīng)度
     */
    public static function combination($latitude_str, $longitude_str)
    {
        $str = "";
        for ($i = 0; $i < strlen($longitude_str); $i++) {//根據(jù)精度表,可發(fā)現(xiàn)維度>=精度
            $str .= $longitude_str{$i};
            if(isset($latitude_str{$i})){
                $str .=  $latitude_str{$i};
            }
        }
        return $str;
    }

    public static function geohash_encode($str)
    {
        $str_arr    = str_split($str, 5);//按5位分割字符串
        $encode_str = "";
        foreach ($str_arr as $va) {
            $decimal    = bindec($va);
            $encode_str .= self::BASE32[$decimal];
        }
        return $encode_str;
    }
    /**
     * 編碼
     */

    /**
     * 解碼
     */
    public static  function geohash_decode($str)
    {
        //根據(jù)一位字符串進(jìn)行切割
        $str_arr    = str_split($str, 1);
        $decode_str = "";
        $base32     = array_flip(self::BASE32);
        foreach ($str_arr as $va) {
            $decode_str .= str_pad(decbin($base32[$va]),5,"0",STR_PAD_LEFT);
        }
        return (string)$decode_str;

    }

    /**
     * 解碼二進(jìn)制組合
     * @param $str
     * @return array
     */
    public static function de_combination($str)
    {
        $latitude_str  = "";
        $longitude_str = "";
        //根據(jù)兩位字符串切割
        $str_arr = str_split($str, 2);
        foreach ($str_arr as $va) {
            $longitude_str .= $va[0];
            if(isset($va[1])){//根據(jù)精度表,可發(fā)現(xiàn)維度>=精度
                $latitude_str  .= $va[1];
            }
        }
        return array(
            self::LATITUDE=>$latitude_str,
            self::LONGITUDE=>$longitude_str,
        );
    }

    /**
     * 解碼二分區(qū)間
     * @param $str
     * @param string $i//執(zhí)行次數(shù)
     * @param array $data、、區(qū)間
     */
    public static function de_separate($str,$i=1,$data = array("min" => -90, "max" => 90)){
        $count   = ($data["max"] - $data["min"]) / 2;
        $limit_0 = array(
            "min" => $data["min"],
            "max" => $data["min"] + $count
        );
        $limit_1 = array(
            "min" => $data["min"] + $count,
            "max" => $data["max"]
        );
        if($str[$i-1]==0){
            $data = $limit_0;
        }else{
            $data = $limit_1;
        }

        if ($i >= strlen($str)) {
            return $data;
        } else {
            return self::de_separate($str, $i + 1, $data);
        }
    }

    /**
     * 解碼
     */

    /**
     * 根據(jù)精度獲取二分次數(shù)
     * @param $level
     * @param $type
     */
    public static function get_precision_level_num($level, $type = self::LATITUDE)
    {
        $precision = array(
            1  => array(
                self::LATITUDE  => 2,
                self::LONGITUDE => 3,
            ),
            2  => array(
                self::LATITUDE  => 5,
                self::LONGITUDE => 5,
            ),
            3  => array(
                self::LATITUDE  => 7,
                self::LONGITUDE => 8,
            ),
            4  => array(
                self::LATITUDE  => 10,
                self::LONGITUDE => 10,
            ),
            5  => array(
                self::LATITUDE  => 12,
                self::LONGITUDE => 13,
            ),
            6  => array(
                self::LATITUDE  => 15,
                self::LONGITUDE => 15,
            ),
            7  => array(
                self::LATITUDE  => 17,
                self::LONGITUDE => 18,
            ),
            8  => array(
                self::LATITUDE  => 20,
                self::LONGITUDE => 20,
            ),
            9  => array(
                self::LATITUDE  => 22,
                self::LONGITUDE => 23,
            ),
            10 => array(
                self::LATITUDE  => 25,
                self::LONGITUDE => 25,
            ),
            11 => array(
                self::LATITUDE  => 27,
                self::LONGITUDE => 28,
            ),
            12 => array(
                self::LATITUDE  => 30,
                self::LONGITUDE => 30,
            ),
        );
        return $precision[$level][$type];

    }

    /**
     * 獲取區(qū)間
     * @param $type
     * @return mixed
     */
    public static function get_interval_value($type = self::LATITUDE)
    {
        $interval = array(
            self::LATITUDE  => array(
                "min" => -90,
                "max" => 90
            ),
            self::LONGITUDE => array(
                "min" => -180,
                "max" => 180
            ),
        );
        return $interval[$type];
    }
}
精度值

如圖,當(dāng)前綴碼相同為7相差76米左右,為8相差19米,為9的話可以近似理解為那個(gè)人就在你身邊了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30978.html

相關(guān)文章

  • 【戴嘉樂(lè)】基于IPFS和GeoHash構(gòu)建具有地理位置價(jià)值服務(wù)DDApp(理論篇)

    摘要:數(shù)據(jù)將具有如下個(gè)特點(diǎn)將二維的經(jīng)緯度轉(zhuǎn)換成字符串,比如下圖展示了北京個(gè)區(qū)域的字符串,分別是,等等,每一個(gè)字符串代表了某一矩形區(qū)域。例如,坐標(biāo)對(duì),位于北京安定門附近,后形成的值為。 作者簡(jiǎn)介:戴嘉樂(lè)( Mr.Maple ) | 前百度高級(jí)研發(fā)工程師 | IPFS應(yīng)用實(shí)踐者&布道師|個(gè)人網(wǎng)站:https://www.daijiale.cn聯(lián)系方式:微信號(hào):daijiale6239。 show...

    lmxdawn 評(píng)論0 收藏0
  • 從拿到班車手冊(cè).xls到搜索附近班車地點(diǎn)

    摘要:輾轉(zhuǎn)流傳出班車手冊(cè)后發(fā)現(xiàn)搜索實(shí)在是太不方便了,于是有了一個(gè)主義,想做一個(gè)可以搜索房子地址,找出附近班車點(diǎn)類似大眾點(diǎn)評(píng)的定位搜索附近餐館的功能。 起因 七月份要去某廠報(bào)道了,異地租房的時(shí)候發(fā)現(xiàn)想租一個(gè)有公司班車的地方,卻不知道哪里有班車。輾轉(zhuǎn)流傳出班車手冊(cè)后發(fā)現(xiàn)搜索實(shí)在是太不方便了,于是有了一個(gè)主義,想做一個(gè)可以搜索房子地址,找出附近班車點(diǎn)(類似大眾點(diǎn)評(píng)的定位搜索附近餐館的功能)?,F(xiàn)在做...

    jhhfft 評(píng)論0 收藏0
  • 淺談附近地點(diǎn)搜索

    摘要:編碼的前綴可以表示更大的區(qū)域,查找附近的,非常方便。百度拾取坐標(biāo)地址編碼精度為位時(shí),大概為附近千米。在經(jīng)度相等的情況下緯度每隔度,距離相差約米每隔度,距離相差約米每隔度,距離相差約米每隔度,距離相差約米每隔度,距離相差約米。 隨著移動(dòng)端的普及,很多 App應(yīng)用 都有 LBS 功能。 附近的銀行、 附近的飯店、 附近的超市、 附近的廁所、 ... 以上的需求很類似,實(shí)現(xiàn)的原理也大致相同。...

    褰辯話 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<