Domanda

Sto cercando di generare una query e avere difficoltà a trovare il modo più efficiente per farlo in SQLalchemy, (Nota che sto usando Flask-SQLalchemy)

L'obiettivo è trovare tutti gli utenti hanno una riunione con un utente specifico.

Quindi diciamo che Frank ha 10 incontri in arrivo, voglio generare un elenco di tutte le persone che Frank ha un incontro con.

Ecco i miei modelli:

class UserMeeting(db.Model):
    """ Associative table, links meetings to users in a many to many fashion"""
    __tablename__ = 'userMeeting'
    id = db.Column(db.Integer, primary_key = True)
    meeting_id = db.Column(db.Integer, db.ForeignKey('meeting.id'), primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)

class Meeting(db.Model):
    __tablename__ = "meeting"
    id = db.Column(db.Integer, primary_key = True)
    title = db.Column(db.String(128))
    #... other columns
    #associative reference
    attendees = db.relationship('UserMeeting', backref='meeting')

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key = True)
    email = db.Column(db.String(128), index=True, unique=True)
    password = db.Column(db.String(128))
    #associative reference
    attendingMeetings = db.relationship("UserMeeting", backref="user", cascade="all, delete-orphan") 
.

Ecco cosa ho provato:

#Assume frank's a user with id == 1
frank = User.query.get(1)
franks_meetings = Meeting.query.join(Meeting.attendees).filter(UserMeeting.user == frank).all()
#not efficient way of getting users in meetings with frank
users = []
for meeting in franks_meetings:
    for userMeeting in meeting.attendees:
        if userMeeting.user != frank:
            users.append(userMeeting.user)

#is there a way to just generate one query and get this data?
.

Mi sembra di sapere come potrei solo usare i join per ottenere questi dati.Qualsiasi aiuto sarebbe apprezzato!

È stato utile?

Soluzione

È necessario unire la tabella USerMeeting con se stessa, usando Meeting_id come chiave di join.Potrebbe essere necessario alias la tabella per farla fare due volte.Non so se posso digitare la sintassi di sqlalchemy per la parte superiore della mia testa, ma SQL sembra:

select distinct(b.user_id) as other_user_id
from usermeeting a
inner join usermeeting b
on a.meeting_id=b.meeting_id
where a.user_id=1 and b.user_id != 1;
.

e 1 è franco.

Oh, e anche i dettagli dell'utente.Probabilmente potresti finire con gli oggetti User direttamente dal fare questo in SQLalchemy:

select distinct(u.id), u.email
from usermeeting a
inner join usermeeting b
on a.meeting_id=b.meeting_id
inner join users u
on b.user_id=u.id
where a.user_id=1 and b.user_id != 1;
.

Altri suggerimenti

Ecco la versione SQLalchemy della query per riferimento:

#get all users in meetings with Frank, (frank.id == 1)
um = aliased(UserMeeting)
frank = User.query.get(1)

q = session.query(User).join(User.attendingMeetings).\
    filter(UserMeeting.meeting_id == um.meeting_id).\
    filter(UserMeeting.user_id != frank.id, um.user_id == frank.id)

users_meeting_with_frank = q.all()
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top