class Searcher(object): def __init__(self, aerospike_connector): self._search_index = SearchIndex(aerospike_connector) def search(self, params): if params.features == None or len(params.features) == 0: signs = self._search_nearest(params) else: signs = self._search_by_fea(params) return self._make_result(params, signs) def _records_processor(self, params, heap): def _impl(record): entry = SearchEntry() entry.sign_id = int(record['sign_id']) entry.rank = record.get('rank') # Min rank threshold if entry.rank != None and entry.rank < params.min_rank: return # Legacy if entry.rank == None: entry.rank = 0 location = record['location'].unwrap().get('coordinates') entry.distance = geo.distance(params.latitude, params.longitude, location[1], location[0]) heap.push(entry) return _impl def _search_nearest(self, params): heap = SearchResultsHeap(params.max_n, lambda entry: -entry.distance) # Retrieve records self._search_index.search_nearest(params.user_id, \ params.latitude, \ params.longitude, \ params.radius, \ self._records_processor(params, heap)) # Resort signs = heap.results.values() signs.sort(key=lambda entry: entry.distance) return signs def _search_by_fea(self, params): heap = SearchResultsHeap(params.max_n, lambda entry: entry.rank) # Normailize features vector qsum = 0 for fea in params.features: qsum = qsum + fea * fea qsum = math.sqrt(qsum) for i in range(len(params.features)): params.features[i] = params.features[i] / qsum # Retrieve records self._search_index.search_by_fea(params.user_id, \ params.latitude, \ params.longitude, \ params.radius, \ params.features, \ self._records_processor(params, heap)) # Resort signs = heap.results.values() if params.sort_by == SearchParams.SORT_BY_RANK or \ params.sort_by == SearchParams.SORT_BY_UNKNOWN: signs.sort(key=lambda entry: entry.rank, reverse=True) else: signs.sort(key=lambda entry: entry.distance) return signs def _make_result(self, params, signs): signs_list = list() for sign in signs: signs_list.append({ 'sign_id': sign.sign_id, 'distance': sign.distance }) debug = None if params.debug: weights = list() for sign in signs: weights.append({ 'sign_id': sign.sign_id, 'weight': sign.rank }) debug = { 'weights': weights } return signs_list, debug