Players take part in events. They should provide information if they're going to attend an event or not.
I want to select players that haven't provided information, if they plan to attend specific event.
As being a beginner in the technologies used, I would appreciate your validation and recommendation for improvement of the solution suggested by me below.
Technologies: python, postgreSQL, and Pony ORM
Entity model in Pony ORM:
class Event(db.Entity):
_table_ = "event"
start = Required(date)
players = Set("Attendance")
class Player(db.Entity):
_table_ = "player"
first_name = Optional(str)
last_name = Required(str)
phone_number = Required(str)
email = Required(str)
events = Set("Attendance")
class Attendance(db.Entity):
_table_ = "attendance"
event = Required(Event)
player = Required(Player)
status = Required(bool)
PrimaryKey(event, player)
Idea:
Current implementation of the idea:
players = select(p for p in Player if p not in select(p for p in Player
for a in Attendance if p == a.player and a.event == next_event))
It is possible to refactor your query to make it more simple. At first, we can replace explicit join of Player
and Attendance
inside the inner query to implicit join via attribute access:
select(p for p in Player if p not in select(p for p in Player
for attendance in p.events if attendance.event == next_event))
To simplify query further we can use attribute lifting by writing expression p.events.event
:
select(p for p in Player if p not in select(
p for p in Player if next_event in p.events.event))
p.events
expression returns a set of Attendance
records. In Pony when you have a set instance this set has all attributes of its items, and when you access such attribute you will get a set of all values of corresponding items attribute. The value of expression p.events.event
will be the set of all Event
objects linked with particular player.
The next step to simplify the query is to replace generators to lambdas. This way the query looks a bit shorter:
Player.select(lambda p: p not in Player.select(
lambda p: next_event in p.events.event))
But the biggest simplification can be achieved if we realize that the inner query is unnecessary and rewrite query as:
Player.select(lambda p: next_event not in p.events.event)
I think this is the most concise way to write this query using PonyORM