Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modelling many-to-many with relation data in Google App Engine

I have two models in my application, Transaction and Person, with a many-to-many relationship. There are persons included in each Transaction. For each person, there is also a amount connected to each Transaction the Person is connected to. Therefor I need to model a many-to-many relationship with relation data. Google suggest this approach:

http://code.google.com/intl/sv-SE/appengine/articles/modeling.html

With this approach I have a model like this:

class TransactionPerson(db.Model):
    # References
    transaction = db.ReferenceProperty(Transaction, required=True)
    person = db.ReferenceProperty(Person, required=True)
    # Values
    amount = db.FloatProperty(required=True)

But I find that very bad for performance because if I need to summarize the amount for each Person in all Transactions I need to loop Person*Transaction*TransactionPerson times to implement the "join" while summing the amounts.

MY IDEA

My idea is to have two lists in the Transaction model:

class Transaction(db.Model):
    persons = ListProperty(db.Key)
    persons_amount = ListProperty(float)

This way I don't need to loop through all TransactionPerson for each Person to find the associated Transaction. And I can still query Transactions based on a Person.

QUESTIONS

  1. Is this possible? Can you trust that the list order is always the same when storing/retriving so the indexes sync between the lists?
  2. Is this a good way to implement many-to-many relationship with associated data?
like image 990
thejaz Avatar asked Aug 11 '11 12:08

thejaz


2 Answers

I suspect you're solving the wrong problem. The intermediate association entity is a good approach. The problem you have is that summaries take a long time to compute; You should be concerned more about that;

The preferred approach is to calculate the summary data ahead of time.

In the specific case of "Transaction totals per Person" that would mean you want to add an extra field to the Person model and update it with a running total of all of their transactions. You would update this any time a TransactionPerson is modified, so that the summary value is always correct.

like image 165
SingleNegationElimination Avatar answered Nov 15 '22 22:11

SingleNegationElimination


1. Yes, you can rely on the order being maintained. From the docs:

when entities are returned by queries and get(), the list properties values are in the same order as when they were stored. There's one exception to this: Blob and Text values are moved to the end of the list; however, they retain their original order relative to each other.

2. Yes, ListProperties are your friends for de-normalizing relationships. I tend to duplicate data a lot, and use list-properties like 'caches' of de-normalized data in this way.

like image 44
Chris Farmiloe Avatar answered Nov 15 '22 21:11

Chris Farmiloe