modelling in google-datastore: use lists or separa

2019-07-22 08:27发布

I'm stuck trying to implement a data model for an app to be deployed on AppEngine.

Here's an example of the model:

EntityName
  id:  1
  author:       'me'
  description:  'whatever'
  datetime:     2011 etc.
  events: [
    {location: [1,2], phase: ['A', 'B']},
    {location: [3,4], phase: ['C', 'B']},
    ... more events ...
  ]

Explanation:

  • EntityName has a few attributes, and many events
  • each event has a list of numbers (its location) and a list of strings (phase)

How can this model be implemented in AppEngine? The data only needs to be searchable by id, author, datetime, and description.


What I've tried to figure out how to do (still going through the docs) (sticking point in italics):

  1. one table, EntityName, with events as a ListProperty
    this would require nested lists in one table ... not sure if that's possible
  2. two tables, EntityName and Event
    needs a join, which I understand isn't directly possible

2条回答
迷人小祖宗
2楼-- · 2019-07-22 09:06

Here's an alternative that only uses one model (i.e., Nick's idea):

import webapp2
from google.appengine.ext import db

class EntityName(db.Model):
    author = db.StringProperty()
    # ...
    event_locations = db.StringListProperty(indexed=False)
    event_phases    = db.StringListProperty(indexed=False)

class MainHandler(webapp2.RequestHandler):
    def get(self):
        e = EntityName(author='me',
            event_locations=['1,2', '3,4'], event_phases=['A,B', 'C,D'] )
        e.put()

        q = EntityName.all().filter('author =', 'me')
        text = ''
        for en in q:
            for locations, phases in zip(en.event_locations, en.event_phases):
                text += "location=%s, phase=%s<br>" % (locations, phases)
        self.response.out.write(text)

app = webapp2.WSGIApplication([('/', MainHandler)], debug=True)    

Sample output:

location=1,2, phase=A,B
location=3,4, phase=C,D

Since order is generally preserved in List and StringList properties, your locations and phases for an event can be matched up -- i.e., they have the same index in the two lists.

With one model you have to do a little more work splitting out each entry in the list, but you save on datastore reads and writes, since you only have one entity.

查看更多
淡お忘
3楼-- · 2019-07-22 09:17

These aren't tables, exactly, but I think this should work for you

class EntityName(db.Model):
    author = db.StringProperty(...)

class Event(db.Model):
    entity_name = db.ReferenceProperty(EntityName, collection_name='events')
    location = db.StringListProperty()
    phase = db.StringListProperty()

Then...

e = EntityName(author='me', ...)
e.put()
event = Event(entity_name=e, location=...)
event.put()

for ev in e.events:
    print ev.location
    print ev.phase

See the documentation for details. You don't need to "do a join" because this isn't a SQL database. For your convenience, collection_name will create an iterator on the referenced side of a one-to-many relationship.

查看更多
登录 后发表回答