Domanda

Esempio di problema:

Entità:

  • L'utente contiene il nome e un elenco di amici (riferimenti utente)
  • Il post sul blog contiene titolo, contenuto, data e scrittore (utente)

Requisiti:

Voglio una pagina che mostri il titolo e un link al blog degli ultimi 10 post dell'amico di un utente. Vorrei anche la possibilità di continuare a sfogliare le voci più vecchie.

Soluzione SQL:

Quindi in sql land sarebbe qualcosa di simile:

select * from blog_post where user_id in (select friend_id from user_friend where user_id = :userId) order by date

Le soluzioni GAE che mi vengono in mente sono:

  • Carica utente, fai scorrere l'elenco degli amici e carica i loro ultimi post sul blog. Infine, unisci tutti i post del blog per trovare gli ultimi 10 post del blog
  • In un post di blog è presente un elenco di tutti gli utenti che hanno lo scrittore come amico. Ciò significherebbe una lettura semplice ma comporterebbe un sovraccarico di quote quando si aggiunge un amico che ha molti post sul blog.

Non credo che nessuna di queste soluzioni scalerà.

Sono sicuro che altri abbiano riscontrato questo problema ma ho cercato, guardato video di Google io, letto il codice di altri ... Cosa mi sto perdendo?

È stato utile?

Soluzione 2

Questo argomento è trattato in un discorso su Google io: http://code.google.com/events/io/sessions/BuildingScalableComplexApps. html

Fondamentalmente il team di Google suggerisce di utilizzare le proprietà dell'elenco e quelle che chiamano entità dell'indice relazionale, un'applicazione di esempio può essere trovata qui: http://pubsub-test.appspot.com/

Altri suggerimenti

Se guardi come verrà eseguita la soluzione SQL che hai fornito, andrà sostanzialmente così:

  1. Recupera un elenco di amici per l'utente corrente
  2. Per ciascun utente nell'elenco, avvia una scansione dell'indice sui post recenti
  3. Unisci tutte le scansioni dal passaggio 2, arrestandoti quando hai recuperato abbastanza voci

Puoi eseguire tu stesso la stessa procedura in App Engine, usando le istanze Query come iteratori e unendo l'unione su di esse.

Hai ragione sul fatto che questo non si ridimensionerà bene per un gran numero di amici, ma soffre esattamente degli stessi problemi che ha l'implementazione di SQL, ma non li maschera anche: recuperare gli ultimi 20 (ad esempio) le voci costano all'incirca O (n log n) lavoro, dove n è il numero di amici.

" Carica utente, fai scorrere l'elenco degli amici e carica i loro ultimi post sul blog. "

Questo è tutto ciò che è un join: loop nidificati. Alcuni tipi di join sono loop con ricerche. La maggior parte delle ricerche sono solo loop; alcuni sono hash.

" Infine, unisci tutti i post del blog per trovare gli ultimi 10 post di blog "

Questo è un ORDER BY con un LIMIT. Questo è ciò che il database sta facendo per te.

Non sono sicuro di cosa non sia scalabile al riguardo; è comunque quello che fa un database.

Ecco un esempio in Python che brillava da http://pubsub-test.appspot.com/:

Qualcuno ne ha uno per Java? Grazie.

from google.appengine.ext import webapp

from google.appengine.ext import db

class Message(db.Model):
 body = db.TextProperty(required=True)
 sender = db.StringProperty(required=True)
 receiver_id = db.ListProperty(int)

class SlimMessage(db.Model):
 body = db.TextProperty(required=True)
 sender = db.StringProperty(required=True)

class MessageIndex(db.Model):  
 receiver_id = db.ListProperty(int)

class MainHandler(webapp.RequestHandler):

 def get(self):
  receiver_id = int(self.request.get('receiver_id', '1'))
  key_only = self.request.get('key_only').lower() == 'on'
  if receiver_id:
    if key_only:
      keys = db.GqlQuery(
          'SELECT __key__ FROM MessageIndex WHERE receiver_id = :1',
          receiver_id).fetch(10)
      messages.extend(db.get([k.parent() for k in keys]))
    else:
      messages.extend(Message.gql('WHERE receiver_id = :1',
                      receiver_id).fetch(10))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top