Geoalchemy2 запрашивает всех пользователей в пределах X метров

У меня есть приложение, которое берет адресную строку, отправляет ее в API Карт Google и получает широкие / длинные координаты. Затем я хочу показать всех пользователей в пределах X метров этой точки (там lat / long хранится в моей базе данных) , То я хочу, чтобы фильтр был результат, чтобы показывать только пользователей с некоторыми домашними животными

Итак, во-первых, у меня есть мои модели

class User(UserMixin, Base): first_name = Column(Unicode) address = Column(Unicode) location = Column(Geometry('POINT')) pets = relationship('Pet', secondary=user_pets, backref='pets') class Pet(Base): __tablename__ = 'pets' id = Column(Integer, primary_key=True) name = Column(Unicode) user_pets = Table('user_pets', Base.metadata, Column('user_id', Integer, ForeignKey('users.id')), Column('pet_id', Integer, ForeignKey('pets.id')) ) 

Я получаю свой lat / long от Google API и сохраняю его в своей базе данных, поэтому из адресной строки «London England» я получаю

 POINT (-0.1198244000000000 51.5112138999999871) 

это хранится в моей базе данных:

 0101000000544843D7CFACBEBF5AE102756FC14940 

Теперь, когда все работает нормально, теперь я читаю документы Geoalchemy2, которые, по-видимому, не могут найти запрос exmaple для решения моей проблемы.

То, что я хочу передать, – это еще один набор лат / длинных координат для Geoalchemy2, а затем верните ближайших 10 пользователей. Пока я прошу об этом, я также буду фильтровать только пользователей, у которых есть определенные домашние животные (это не обязательно для моего запроса на работу, но я хотел показать, что запрос действительно будет делать в полном объеме).

Я не очень люблю отвечать на вопрос, не предлагая пример запроса, но я действительно не знаю, какие функции я должен использовать для достижения моего требуемого результата.

Я предполагаю, что мне нужно будет использовать «ST_DWithin» или «ST_DFullyWithin», но я не могу найти полный пример любой из функций. Благодаря.

Поэтому у меня есть рабочий запрос

 distance = 10 address_string = "London, England" results = Geocoder.geocode(address_string) # load long[1], lat[0] into shapely center_point = Point(results.coordinates[1], results.coordinates[0]) print center_point # 'POINT (-0.1198244000000000 51.5112138999999871)' wkb_element = from_shape(center_point) users = DBSession.query(User).\ filter(func.ST_DWithin(User.location, wkb_element, distance)).all() 

Что генерирует следующий SQL

 2013-12-30 15:12:06,445 INFO [sqlalchemy.engine.base.Engine][Dummy-2] SELECT users.first_name AS users_first_name, users.last_name AS users_last_name, users.phone AS users_phone, users.address AS users_address, users.about AS users_about, ST_AsBinary(users.location) AS users_location, users.profile_image_id AS users_profile_image_id, users.searchable AS users_searchable, users.user_password AS users_user_password, users.registered_date AS users_registered_date, users.id AS users_id, users.last_login_date AS users_last_login_date, users.status AS users_status, users.user_name AS users_user_name, users.email AS users_email, users.security_code AS users_security_code FROM users WHERE ST_DWithin(users.location, ST_GeomFromWKB(%(ST_GeomFromWKB_1)s, %(ST_GeomFromWKB_2)s), %(param_1)s) 2013-12-30 15:12:06,445 INFO [sqlalchemy.engine.base.Engine][Dummy-2] {'ST_GeomFromWKB_1': <read-only buffer for 0x7f7d10258f70, size -1, offset 0 at 0x7f7d10258db0>, 'param_1': 10, 'ST_GeomFromWKB_2': -1} 

Теперь это всегда возвращает всех моих пользователей, независимо от переменной расстояния, поэтому я угадываю, что что-то не так, правильно, но я не могу понять, почему.

2 Solutions collect form web for “Geoalchemy2 запрашивает всех пользователей в пределах X метров”

Ответ:

Единицы были в радиусе градуса, поэтому мне пришлось перевести милю в дегресс, чтобы получить наилучшую (грубую) оценку. Это не обязательно должно быть точным:

 d = 90 distance = d * 0.014472 #1 mile = 0.014472 degrees r1 = -0.1198244 r2 = 51.5112139 # load long[1], lat[0] into shapely center_point = Point(r1, r2) # 'POINT (-0.1198244000000000 51.5112138999999871)' wkb_element = from_shape(center_point) users = DBSession.query(User).\ filter(func.ST_DFullyWithin(User.location, wkb_element, distance)).all() 

Данные Lat / Lon не подходят для расчетов расстояний.

Каждая градус широты составляет приблизительно 69 миль (111 километров) друг от друга. Диапазон варьируется (из-за слегка эллипсоидной формы земли) от 68,703 миль (110,567 км) на экваторе до 69,407 (111,699 км) на полюсах. Это удобно, потому что каждая минута (1/60 градуса) составляет примерно одну милю.

Степень долготы наиболее широка на экваторе на 69,172 миль (111,321) и постепенно сжимается до нуля на полюсах. На 40 ° севернее или юг расстояние между степенью долготы составляет 53 мили (85 км).

Вы можете использовать ST_Transform для преобразования координат в другую проекцию, которая использует метры или мили. Они имеют тенденцию быть локальными, поскольку они проектируют сферу Земли на растрированную плоскость. Британская национальная сетка (SRID 27700) может соответствовать вашим потребностям.

  • Правильная обработка SQLAlchemy сеанса в многопоточных приложениях
  • SQLAlchemy: лучший способ для обновления с декларативным?
  • Простой оператор SELECT в существующей таблице с SQLAlchemy
  • Текстовое поле Readonly в Flask-Admin ModelView
  • Ошибка SQLAlchemy Сервер MySQL ушел
  • SQLALchemy dynamic filter_by
  • Обновление SQLAlchemy, если существует уникальный ключ
  • SQLAlchemy и Falcon - инициализация сеанса
  • Python - лучший язык программирования в мире.