def get_geohash_where_clause(coord_geoint, precision, geoint_col_name):
    '''
    Given an unsigned 64-bit int geohash, a precision, and the SQL table
    column name of the geohash field, returns a SQL WHERE clause that
    would select all rows within the distance bounded by the specified
    precision. If the precision is low enough such that no WHERE clauses
    can be generated, empty str is returned.

    coord_geoint: unsigned 64-bit int, geohash value of the coordinates
                    around which to query for.
    precision: the precision to search within, the lower the value the
                larger the distance to search for. Must be between 0
                and 64.
    geoint_col_name: the name of the geohash int column in the SQL
                    database table to search in.
    '''

    sub_clauses = []
    for bound_range in geohash.expand_uint64(coord_geoint, precision):
        if bound_range[0] and bound_range[1]:
            sub_clauses.append("(" + geoint_col_name + ">=" + str(bound_range[0]) + " AND " + geoint_col_name + "<" + str(bound_range[1]) + ")")
        elif bound_range[0]:
            sub_clauses.append("(" + geoint_col_name + ">=" + str(bound_range[0]) + ")")
        elif bound_range[1]:
            sub_clauses.append("(" + geoint_col_name + "<" + str(bound_range[1]) + ")")
    if len(sub_clauses) == 0:
        return ""
    else:
        return "(" + " OR ".join(sub_clauses) + ")"
Exemplo n.º 2
0
Arquivo: api.py Projeto: akosel/a2bus
def get_nearest_stops(key, lng, lat, radius=150, units='m', with_dist=False, with_coord=False, with_hash=False, sort=None):
    if not api_redis.exists('locations'):
        set_cache_stops()
    pieces = [key, lng, lat, radius, units]

    # XXX Can modify precision based on user radius. Default to 36 (~150m)
    ranges = geohash.expand_uint64(geohash.encode_uint64(float(lat), float(lng)), precision=36)

    # XXX This has no affect at this time
    if with_dist:
        pieces.append('WITHDIST')
    if with_coord:
        pieces.append('WITHCOORD')
    if with_hash:
        pieces.append('WITHHASH')
    if sort:
        pieces.append(sort)

    # TODO Some day this can be done with the Geo Redis commands
    pipe = api_redis.pipeline(transaction=False)
    for r in ranges:
        pipe.zrangebyscore(key, r[0], r[1])

    # TODO This will require some intermediate steps if scores are returned
    stops = [stop for stop_list in pipe.execute() for stop in stop_list]
    # TODO Implement filtering by radius and units
    return get_stop_details(stops)
Exemplo n.º 3
0
    def apply_filters(self, request, applicable_filters):
        r = applicable_filters.pop('range')
        if not 'geohash__exact' in applicable_filters:
            return super(BeatResource, self).apply_filters(request, applicable_filters)
        gh = long(applicable_filters.pop('geohash__exact'))

        # Use Q object to query the neighbors of the geohash
        qobj = Q()
        for nb in geohash.expand_uint64(gh, r):
            qobj |= Q(geohash__gt=nb[0], geohash__lt=nb[1])
        return super(BeatResource, self).apply_filters(request, applicable_filters).filter(qobj)
Exemplo n.º 4
0
 def _expand(self, ui64, depth):
     return geohash.expand_uint64(ui64, depth)