2011-08-11 3 views
6

Ho due modelli nella mia applicazione, Transazione e Persona, con una relazione molti-a-molti. Ci sono persone incluse in ogni Transazione. Per ogni persona, c'è anche una somma collegata a ciascuna Transazione a cui è connessa la Persona. Perciò ho bisogno di modellare una relazione molti-a-molti con i dati di relazione. Google Suggest questo approccio:Modellazione molti-a-molti con dati di relazione in Google App Engine

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

Con questo approccio ho un modello come questo:

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

Ma trovo che molto male per le prestazioni, perché se ho bisogno di riassumere la quantità per ogni persona in tutte le Transazioni ho bisogno di ciclizzare Persona * Transazione * TransactionPerson volte per implementare il "join" mentre sommando gli importi.

mia idea

La mia idea è quella di avere due liste nel modello di transazione:

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

In questo modo non ho bisogno di ciclo di tutti TransactionPerson per ogni persona di trovare la associato Transazione. E posso ancora interrogare le transazioni in base a una persona.

DOMANDE

  1. è possibile? Puoi fidarti del fatto che l'ordine delle liste è sempre lo stesso quando si memorizza/rientra e quindi gli indici si sincronizzano tra gli elenchi?
  2. È un buon modo per implementare la relazione molti-a-molti con i dati associati?

risposta

2

Sospetto che tu stia risolvendo il problema sbagliato. L'entità di associazione intermedia è un buon approccio. Il problema che hai è che i riepiloghi impiegano molto tempo per essere calcolati; Dovresti preoccuparti di più di questo;

L'approccio preferito è calcolare anticipatamente i dati di riepilogo.

Nel caso specifico di "Totali transazioni per persona", ciò significa che si desidera aggiungere un campo aggiuntivo al modello Persona e aggiornarlo con un totale parziale di tutte le transazioni. Si aggiornerà ogni volta che un TransactionPerson viene modificato, in modo che il valore di riepilogo sia sempre corretto.

+0

Ma perché l'ente di un'associazione intermedia è un buon approccio quando causerà operazioni meno efficienti? Ad esempio con il tuo approccio; se una Transazione viene aggiornata, spesso devo aggiornare tutti gli oggetti Person associati alla Transazione. Non ne ho bisogno se utilizzo il mio approccio? Quali sono le ragioni per cui è meglio utilizzare un'entità di associazione? – thejaz

+0

O potrebbe essere la scelta migliore per quello che stai facendo, ma la mia risposta si concentra sulla specifica questione del calcolo dei dati di riepilogo. Se devi caricare più di una manciata di entità per soddisfare una particolare richiesta, probabilmente devi trovare un modo per estrarre quel processo dalla richiesta e crearlo in un altro modo, come quando il valore cambierebbe. – SingleNegationElimination

+0

I dati di riepilogo erano solo un esempio. Spesso desidero ottenere tutte le persone in una Transazione che nella pratica si traduca nella stessa Persona * Transazione * TransactionPerson cicli che non devono essere accettabili per quanto riguarda le prestazioni, anche se lo faccio più raramente (quando aggiungo o modifica un TransactionPerson). Anche se dovessi memorizzare nella cache i dati (una lista di persone) sulla Transazione, sarebbe lo stesso di quello che ho suggerito nella mia domanda, ma con l'aggiunta di avere anche i dati della relazione in una lista. Non porterebbe a dati duplicati. Come lo faresti? – thejaz

1

1. Sì, puoi contare sull'ordine da mantenere. Da docs:

quando le entità vengono restituite da query e get(), i valori delle proprietà dell'elenco sono nello stesso ordine di quando sono stati memorizzati. C'è un'eccezione a questo: i valori Blob e Text vengono spostati alla fine dell'elenco; tuttavia, mantengono il loro ordine originale l'uno rispetto all'altro.

2. Sì, ListProperties sono i tuoi amici per i rapporti de-normalizzante. Tendo a duplicare molto i dati e ad usare le proprietà delle liste come "cache" di dati non normalizzati in questo modo.

+0

Per quanto riguarda (2), cosa intendi con la duplicazione dei dati? Nel mio caso non è una duplicazione, è solo un modo per memorizzare i dati della realizzazioni? – thejaz

+0

Come a volte manterrò un'impostazione normalizzata, 'A ha molti B' ma ogni volta che salvi' B's', memorizzo anche alcuni dei dati importanti negli elenchi su 'A' per un'elaborazione più rapida in seguito. –