假設我們現在的問題是:「離我最近的5個wifi熱點在哪裡」
工程師看到問題,一般來說,就會想到至少要下面二樣東西才能查找相關資訊
1.我(目標) 目前的位置(經度及緯度)
2.要幾個結果數 (本問題是5個,當然你也可以寫死,比較彈性的方式是多一個參數或設定可以傳入想要的結果數)

 

依上述的問題,我們定義的函數如下
public colleciton<QueryMatch> queryKNN(double lat , double lon , int n)
{
  1.把目標轉成geohash
  2.迴圈找出目標和他的9宮格鄰居內的wifi 熱點資料
  3.對上述找出之資料進行排序,找出最近距離的n  個點回傳

}

大致上的程式碼如下


public Collection<QueryMatch> query(double lat , double lon , int n )
{
    DstanceComparator comp  = new DistanceComparator(lon,lat);
    Collection<QueryMatch> ret = MinMaxPriorityQueue.orderedBy(comp).maximumSize(n).create();
    GeoHsh target = GeoHash.withCharacterPrecision(lat,lon,7);
    //先確認目標地區的grid 有無資料
    ret.addAll( take N( comp , target.toBase32() , n ));
    
    //找出鄰居9宮格並確認grid 有無資料
    for (GeoHash h : target.getAdjacent())
    {
        ret.addAll( takeN(comp,h.toBase32(),n))
    }

    return ret;
}


public Collection<QueryMatch> takeN(Comparator<QueryMatch> comp , String prefix , int n )
{
    Collection<QueryMatch> candidates = MinMaxPriorityQueye.orderBy(comp).maxmumSize(n).create();
    
    Scan scan = new Scan( prefix.getBytes());
    scan.setFilter( new PrefixFilter(prefix.getBytes()))
    scan.addFamily(Family)
    scan.setMaxVersion(1)
    // cache 設置為大於1的值可減少RPC 呼叫 
    scan.setCaching(1)    
    
    HTableInterface table = pool.getTable("wifi")
    ResultScanner scanner = table.getScanner(scan)
    for ( Result r : scanner)
    {
        String hash = new String(r.getRow)
        String id = new String( r.getValue (FAMILY,ID))
        double lon = Bytes.toDouble( r.getValue(FAMILY, X_COL))
        double lat = Bytes.toDuble( r.getValue(FAMILY,Y_COL))
        candidates.add( new QueryMatch(id,hash,lon,lat))
    }
    table.close();
    return candidates;
}

這邊有一個重要的點是,你怎麼知道要使用幾碼geohash去作 row key掃描? 如果用的geohash 太長(精確度太高),則可能無法得到n個符合的資料,如果geohash太短,則可能得到資料比預期多很多的資料量,意思是不同資料和不同n值會需要不同的geohash精確度,所以你必須了解你的資料和系統,才有辦法反覆測試找出一個合理的n值。

(本資訊由HBase-搞定big data-no sql實戰 整理而出)

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 avseq 的頭像
    avseq

    工程師的哭爸

    avseq 發表在 痞客邦 留言(0) 人氣()