简体   繁体   中英

NDB Query for repeated structured property by ancestor

I'm testing following object:

pk = ndb.Key(League, 'Premier League', 'Season', '2012/13')
o = Team(
    id = 'Chelsea',
    name ='Chelsea',
    leagues = [
       TeamInLeague(
           parent = pk,
           position = 1,
       ),],
)
o.put()

and following test fails on AssertionError: 0 != 1 :

q = Team.query(ancestor=pk)
self.assertEqual(q.count(), 1)

I also tried following test:

q = Team.query(TeamInLeague(ancestor=pk))
self.assertEqual(q.count(), 1)

And it fails on AttributeError: type object 'TeamInLeague' has no attribute 'ancestor' .

Is there a way to query by structured property's parent? Or am I doing it all wrong? I understand from the docs that I add parent property on creation.

You cannot use ancestor relationships to do what you want.

In fact you do not supply a parent key when creating your team class. I gather you want the Team object to be created with a League object as parent?

That would look like this:

league_k = ndb.Key(League, 'Premier League', 'Season', '2012/13')
o = Team(
    id = 'Chelsea',
    name ='Chelsea',
    parent = league_k
)
o.put()

However, like that there will be a flaw in your data model. The team class will forever be linked to the League. As the League apparently contains a season, your team will be inaccessible next season.

It is better to use a many-to-many relationship, as you already started in your example code. That would involve creating a helper class TeamInLeague, as you already did. You can then use normal queries (not ancestor queries) to determine what team is in what league. However, in this case, I would consider creating a special TeamInLeague class. This conceptually cleaner than using repeated properties, especially repeated structured properties.

Also, it is not required that you specify all object properties in the constructor. This is not jQuery. In many cases it is more readable to create object relationships after you have created the object and before the put().

Your code would look like this:

league_k = ndb.Key(League, 'Premier League', 'Season', '2012/13')
team = Team(id = 'Chelsea', name ='Chelsea')
o.put()
team_in_league = TeamInLeague(team=team.key(), league=league_k, pos=1)
team_in_league.put()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM