How to perform a many-to-many filter using Referen

2019-06-02 04:34发布

问题:

This is my model, Players and Clubs. As a Club can have many players and a player can have many clubs (in its carrer), I used a many-to-many relationship:

class Club(db.Model): 
   name = db.StringProperty()  
   link = db.StringProperty()  

 class Player(db.Model): 
   name = db.StringProperty()  
   link = db.LinkProperty()  

 class ClubHasPlayer(db.Model): 
   club = db.ReferenceProperty(Club, required=True,
      collection_name='club_players')
   player = db.ReferenceProperty(Player, required=True,
      collection_name='player_clubs')
   number = IntegerProperty()

Now, I have a search interface where one can search for all players, and add zero or more restrictions, such as player name, and club where he played. Thus, I have a cascade type of handling this:

  players = player.all()

   if filter_by_player_name:
       players.filter("name =",filter_by_player_name)

Now, I want to do this:

   if filter_by_club_name:
       players.filter(????)

I still think in terms of SQL, and it should be something like a nested clause :

select * from player where player.name='x' and player.id in (select club_has_player.player_id from club_has_player, club where club_has_player.club_id = club.id and club_name = "Y")

How to do it?

I know I could go from the club, that is:

club = Club.filter("name =",filter_by_club_name).get() club.club_players

but this style discards a previous filter, that could be player names...

Can anybody help me here? Thanks.

回答1:

One common advice in the GAE community is to denormalize your models. This can be useful in this specific situation. You can store the club name in every player entity as a string, in addition to the reference property to the club:

 class Player(db.Model): 
     name = db.StringProperty()  
     link = db.LinkProperty()
     club = db.ReferenceProperty(club)
     club_name = db.StringProperty()

This would allow you to easily filter Players by club name.

Obviously, this makes changing club names harder. But the probability of having to change a club name is low.