0
votes

I am interested in understanding the pros / cons of several ways to design classes for Google App Engine's Datastore.

Consider the following classes:

Option 0

class Car(db.Model):
    title = db.StringProperty()
    year = db.StringProperty()
    imgurl = db.StringProperty()
    type = db.StringProperty()
    addeddate = db.DateTimeProperty()
    external_id = db.IntegerProperty()
    # possibly 5 or 6 more properties

class Part(db.Model):
    title = db.StringProperty()
    # other stuff

Part's parent is always set to the corresponding Car on creation.

These are used in several ways:

  • query + list (+ sort) parts: when listing the part, I need to display the Car's title, and get its external_id and year (so I don't need everything but the whole Car entity is fetched by accessing the part.parent, I am already using parent prefetch).
  • query + list (+ sort) cars: only need the title, year and imgurl.
  • get car: page with all the car details, need all the properties.

Considering the ways I get and display my data, what is the best option (providing pros/cons) between the above design and the followings?

Option 1

class Car(db.Model):
    title = db.StringProperty()
    year = db.StringProperty()
    imgurl = db.StringProperty()

class CarEx(db.Model):
    type = db.StringProperty()
    addeddate = db.DateTimeProperty()
    external_id = db.IntegerProperty()
    # possibly 5 or 6 more properties
  • Pro: When fetching Parts, getting the parents (Car) is faster since there are less properties.

  • Con: When displaying a Car, we need to get the CarEx. Need to add one more entity when adding a Car. Need to delete CarEx when deleting a Car.

Option 2

class Car(db.PolyModel):
    title = db.StringProperty()
    year = db.StringProperty()
    imgurl = db.StringProperty()

class CarEx(Car):
    type = db.StringProperty()
    addeddate = db.DateTimeProperty()
    external_id = db.IntegerProperty()
    # possibly 5 or 6 more properties

When adding cars, we would only add CarEx entities.

  • Pro: When fetching Parts, getting the parents (Car) is faster since there are less properties. ??? I am actually not sure at all this is true. ???

  • Pro: When displaying a Car, we get the CarEx. No need to get another entity. Adding and deleting cars is as easy as having only 1 Car model with everything in it (Option 0).

  • Con: Extra writes when adding a CarEx. Other extra costs?

So overall, I need to be able to fetch parts (and their parents, without a huge cost), and I need to fetch a full Car on a separate page. I am not sure if my assumptions about PolyModel are correct, nor if there are any other hidden pros/cons, or even other options.

1

1 Answers

2
votes

A few points, If you are starting out, really you should be using ndb.

The small number of properties you list are not going to make enough difference to use Car and CarEx. Especially if you need CarEx all the time.

You use of PolyModel doesn't make sense, given how PolyModel works. Polymodel would be more suited to

class Vehicle(PolyModel):
    title = StringProperty
    year = StringProperty()
    addeddate = db.DateTimeProperty()
    external_id = db.IntegerProperty()
    # possibly 5 or 6 more properties


class Car(Vehicle):
    doors = IntegerProperty

class Van(Vehicle):
    carrying_capacity = FloatProperty() #(m3)

class Truck(Vehicle):
    tray_length = IntegerProperty()

Yep contrived, properties. But now I can search for all vehicles by any of the core Vehicle properties and get Trucks and Vans and Cars. You can't do this with normal model inheritance. Without PolyModel you would have to search Car, Truck entity types seperately.

In your case you probably don't need this.

What you do with Parts depends heavily on how many, and how often you need them. If you are likely to have less than 1MB of Parts and you need all Parts when you need Parts, then consider storeing Parts in a single container entity, and use a repeated StructuredProperty to store them. Then when you need parts you fetch them in a single entity. If you only need some parts then store them as separate entities.

If you need more than 1MB of Parts but you always need all parts then use more than one container.

You really need to look at the frequency of use of particular views, if you need all information vs some of it, to determine the best strategy.