Пример #1
0
    def _get_geodata(self, column, value, multi_op='AND'):
        '''Documentation regarding FTS search: https://www.sqlite.org/fts3.html#full_text_index_queries
		A query such as:
		zipdb.get_geodata(['place_name', 'admin_name1', 'country_code'], ['MADRID', 'MADRID', 'ES'])
		should return something like:
		{	'accuracy': 4.0,
			'admin_code1': 'MD',
			'admin_code2': 'M',
			'admin_code3': '28079',
			'admin_name1': 'MADRID',
			'admin_name2': 'MADRID',
			'admin_name3': 'MADRID',
			'country_code': 'ES',
			'country_name': None,
			'location': '40.4165,-3.7026',
			'place_name': 'MADRID',
			'representative_point': '40.4165,-3.7026',
			'zip_code': '28001'
		}
		'''
        if type(value) is str and type(column) is str and column in self.names:
            query = 'SELECT * FROM {} WHERE {} MATCH "{}:{}"'.format(
                self.name, self.name, column.lower(), value.lower())
        elif type(value) is str and type(
                column) is str and column not in self.names:
            query = 'SELECT * FROM {} WHERE {} MATCH "{}"'.format(
                self.name, self.name, value.lower())
        elif type(column) is list and type(value) is list and len(
                column) == len(value):
            op = ' {} '.format(multi_op)
            query = op.join([
                "{}:{}".format(c.lower(), v.lower())
                for c, v in zip(column, value)
            ])
            query = 'SELECT * FROM {} WHERE {} MATCH "{}"'.format(
                self.name, self.name, query)
        else:
            return None

        self.cursor.execute(query)

        results = self.cursor.fetchall()
        if results is None or len(results) == 0:
            return None
        #else
        d = results[0]
        d['location'] = '{},{}'.format(results[0]['latitude'],
                                       results[0]['longitude'])
        d['representative_point'] = d['location']
        if len(results) > 1:
            geo_points = [(r['latitude'], r['longitude']) for r in results]
            geo_points = MultiPoint(geo_points)
            repr_lat, repr_lon = geo_points.representative_point().coords[0]
            d['representative_point'] = '{},{}'.format(repr_lat, repr_lon)

        del d['latitude']
        del d['longitude']
        d['country_name'] = None

        return d
Пример #2
0
    def _get_geodata(self, column, value, multi_op='AND'):
        """Queries the database.
		:param column: Column to query.
		:param value: Value of the given column. Provide the value in upper case.
		:return: dictionary with geographical information like:
		{
			 'country_code': 'US',
			 'country_name': 'UNITED STATES',
			 'location': {'lat': 37.09024, 'lon': -95.712891},
			 'representative_point': {'lat': 37.09024, 'lon': -95.712891}
		}
		A representative point is a kind of centroid calculated when there are many. For example, if you query with country_code: US, there are many different entries.
		The location dictionary would be populated with the first geopoint, and the rerpesentative_point would be calculated using the method representative_point of a shapely.geometry.MultiPoint
		See https://toblerity.org/shapely/manual.html#object.representative_point
		However, in this database, there should be only one possible entry for each query.
		"""
        if type(column) is str:
            self.cursor.execute('SELECT * FROM {} WHERE {} = "{}"'.format(
                self.name, column, value))
        elif type(column) is list and type(value) is list and len(
                column) == len(value):
            op = ' {} '.format(multi_op)
            query = op.join(
                ['"{}" = "{}"'.format(e[0], e[1]) for e in zip(column, value)])
            query = 'SELECT * FROM {} WHERE {}'.format(self.name, query)
            self.cursor.execute(query)

        results = self.cursor.fetchall()
        if results is None or len(results) == 0:
            return None
        d = results[0]
        d['location'] = '{},{}'.format(results[0]['latitude'],
                                       results[0]['longitude'])
        d['representative_point'] = d['location']
        if len(results) > 1:
            geo_points = [(r['latitude'], r['longitude']) for r in results]
            geo_points = MultiPoint(geo_points)
            repr_lat, repr_lon = geo_points.representative_point().coords[0]
            d['representative_point'] = '{},{}'.format(repr_lat, repr_lon)
        del d['latitude']
        del d['longitude']
        if 'index' in d:
            del d['index']
        return d
Пример #3
0
    def _get_geodata(self, column, value, multi_op='AND', str_ip=True):
        """Queries the database.
		:param column: Column or list of columns to query.
		:param value: Value or list of values of the given column/s. Provide the value/s in upper case.
		:return: dictionary with geographical information like:
		{
			 'place_name': 'MONTERREY',
			 'country_code': 'MX',
			 'country_name': 'MEXICO',
			 'location': {'lat': 25.66667, 'lon': -100.31667},
			 'region_name': 'NUEVO LEON',
			 'representative_point': {'lat': 21.210829999999998, 'lon': -100.21194},
			 'zip_code': '64830'
		}
		"""
        if column == 'ip':
            if str_ip:
                try:
                    value = ip2int(str(value))
                except Exception as e:
                    logger.warning('Error in ip2int with ip: |{}|'.format(
                        str(value)))
                    return None
            idx = bisect.bisect_right(self.ip_int_to_list, value)
            ip_to = self.ip_int_to_list[idx]
            query = 'SELECT * FROM {} WHERE ip_to = "{}"'.format(
                self.name, ip_to)
            #query = 'SELECT * FROM {} WHERE {} BETWEEN ip_from AND ip_to'.format(self.name, value)
        elif type(column) is str:
            query = 'SELECT * FROM {} WHERE {} = "{}"'.format(
                self.name, column, value)
        elif type(column) is list and type(value) is list and len(
                column) == len(value):
            op = ' {} '.format(multi_op)
            query = op.join(
                ['"{}" = "{}"'.format(e[0], e[1]) for e in zip(column, value)])
            query = 'SELECT * FROM {} WHERE {}'.format(self.name, query)
        else:
            return None
        logger.debug('Query: {}'.format(query))

        self.cursor.execute(query)
        results = self.cursor.fetchall()
        logger.debug('Results {}'.format(results))
        if results is None or len(results) == 0:
            return None
        d = results[0]
        d['location'] = '{},{}'.format(results[0]['latitude'],
                                       results[0]['longitude'])
        d['representative_point'] = d['location']
        if len(results) > 1:
            logger.debug('More than 1 result. Creating centroid.')
            geo_points = [(r['latitude'], r['longitude']) for r in results]
            geo_points = MultiPoint(geo_points)
            repr_lat, repr_lon = geo_points.representative_point().coords[0]
            d['representative_point'] = '{},{}'.format(repr_lat, repr_lon)
            logger.debug('Centroid done.')

        for k in ['latitude', 'longitude', 'ip_from', 'ip_to', 'index']:
            if k in d:
                del d[k]

        return d