Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to query Firebase for keys that match a string prefix

Tags:

firebase

Since firebase not support any spatial indexing then I use geohash which someone advice here. Geohash is using characters to find the nearby.

So let say I have w22qt4vhye1c w99qt4vdf4vc w22qt4vhzerct geohash store in firebase and I want to query only which geohash close to w22qt4.

How to do that?

I know firebase has startAt. I tried but not work.

UPDATE

Storing geohash to firebase

//Encode lat lng, result w22qt4vhye1c3
var geoHashLatLng = encodeGeoHash(lat,lng);
firebaseRef.child('/geohash/' + geoHashLatLng).set(id); 

so in json

  root
   - geohash
      - w22qt4vhye1c3
         - id
      - z99qt4vdf4vc
      - w22qt4vhzerct

My question here. I Just want to query geohash which start from characters w22qt4. Can we do that in firebase?

UPDATE 2 startAt() seems like not query with characters start with ...

Example: I have following gehash

geohash node

geohash
  - a123
  - a333
  - b123
  - c123
  - d123

With the following code

var firebaseRef = new Firebase('https://test.firebaseio.com');
var query = firebaseRef.child('/geohash').startAt(null, 'a');
query.on('child_added', function(snapshot) {
    console.log(snapshot.name());
});

Will get this results

startAt(null, 'a') //return a123, a333, b123, c123, d123
startAt(null, 'c123') //return c123, d123
startAt(null, 'd') //return d123

My expected results

startAt(null, 'a') //return a123, a333
startAt(null, 'c123') //return c123
startAt(null, 'd') //return d123

My guess, startAt() will query the 26 alphabet letters in sequence but not matching. So, what can I do in firebase so I can get my expected results above?

like image 774
vzhen Avatar asked Jun 26 '13 19:06

vzhen


1 Answers

In addition to Andrew's answer above, what you want to do to get the desired effect with geohashes (i.e. be able to do prefix queries that let you specify accuracy in the 'query', specifically, for example every 3 characters in the geohash gets you ~ +-80km) is to store the data in a more granular and discretized manner.

So, rather than how you're storing it now, you'll want to save the data by chopping the geohash string key into fragments (I've done it at the 3 character boundary, but you should choose an appropriate tokenization strategy that gives you the desired accuracy) and use each fragment as a child name, as such:

root
  - geohash
      - w22
        - qt4
          - vhy
            - e1c
              - w22qt4vhye1c3
                - id
          - vhz
            - erc
              - w22qt4vhzerct
                - id
      - z99
          - qt4
            - vdf
              - z99qt4vdf4vc
                - id

Then, as in your question, when you need to get all geohashes that start with w22qt4 you would do a query against:

firebaseRef.child('/geohash/w22/qt4/')

Which would then give you the vhy and vhz children which then have all the actual geohashes that you were interested in.

like image 122
Vikrum Avatar answered Oct 09 '22 14:10

Vikrum