Background Schema:
class Checkpoint(db.Model):
id = db.Column(db.Integer, primary_key=True)
creator = db.Column(db.Integer, db.ForeignKey('user.id'))
name = db.Column(db.String(255))
description = db.Column(db.String(255), nullable=True)
price = db.Column(db.Float, nullable=True)
expiry = db.Column(db.DateTime, nullable=True)
date_created = db.Column(db.DateTime)
type = db.Column(db.String(255))
image = db.Column(db.String(255))
longitude = db.Column(db.Float)
latitude = db.Column(db.Float)
class UserCheckpoint(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship("User")
checkpoint_id = db.Column(db.Integer, db.ForeignKey('checkpoint.id'))
checkpoint = db.relationship("Checkpoint")
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255))
facebook_info = db.Column(db.String(255), db.ForeignKey('facebook_user.id'))
facebook_user = db.relationship("FacebookUser")
class FriendConnection(db.Model):
id = db.Column(db.Integer, primary_key=True)
fb_user_from = db.Column(db.String(255), db.ForeignKey('facebook_user.id'))
fb_user_to = db.Column(db.String(255), db.ForeignKey('facebook_user.id'))
class FacebookUser(db.Model):
id = db.Column(db.String(255), primary_key=True)
name = db.Column(db.String(255))
first_name = db.Column(db.String(255), nullable=True)
middle_name = db.Column(db.String(255), nullable=True)
last_name = db.Column(db.String(255), nullable=True)
gender = db.Column(db.String(255), nullable=True)
username = db.Column(db.String(255), nullable=True)
link = db.Column(db.String(255), nullable=True)
I have a user, and as you can see, each user has a Facebook profile, as well as a table depicting inter-facebook-profile friendships. So given the user, the user would have a list of Facebook friends. I would like to get all UserCheckpoints that belong either to the user or his friends, with a given Checkpoint condition:
coord_conditions = and_(Checkpoint.longitude <= longitude + exp_no,
Checkpoint.longitude >= longitude - exp_no,
Checkpoint.latitude <= latitude + exp_no,
Checkpoint.latitude >= latitude - exp_no,
)
How can I do this using the ORM from SQLAlchemy? Thanks!
Summary: How to select UserCheckpoints given that the user_id belong to a list of friends/self; while UserCheckpoint.checkpoint has a set of conditions to fulfill.
Each relation has two methods to defined conditions on related objects:
.has()for single referred object and.any()for collections. These methods allow straightforward translation of your task to SQLAlchemy expression. Let’s add missing relations toFacebookUser:I’ve defined
FacebookUser.userassuming one-to-one relation (which is usually supplemented with unique constraint on the foreign key column). Just removeuselist=Falseand adjust name if you allow several users being connected to one facebook account.A shorter definition of your condition for coordinates:
This condition is definitely wrong even for approximation (-179.9° and 179.9° are very close, while the difference is huge), but this is not main topic of the question.
A condition for users of interest (user with id equal to
user_idand his friends):Now the query is quite simple:
Unless you have (or expect) performance issues, I’d suggest avoid optimizing it at the cost of readability.