2011-02-05 7 views
5

Il Gaelyk tutorial fornisce alcuni interessanti wrapper di basso livello all'archivio dati e this Gaelyk google groups article descrive un modo semplice per modellare le relazioni semplicemente memorizzando le chiavi in ​​una raccolta sull'entità.Gaelyk: come eseguire query di archivio dati sugli attributi di raccolta

La mia domanda è come posso eseguire query sui valori all'interno delle collezioni? Ecco qualche esempio di codice per chiarire ...

def b1 = new Entity("Book") 
b1.title = "Book1" 
b1.save() 

def b2 = new Entity("Book") 
b2.title = "Book2" 
b2.save() 

def author1 = new Entity("Author") 
author1.books = [b1.key, b2.key] 
author1.name = "Chris" 
author1.save() 

// It is easy to simply query the Author entity for a standard string property 
def query = new Query("Author") 
query.addFilter("name", Query.FilterOperator.EQUAL, "Chris") 
PreparedQuery preparedQuery = datastore.prepare(query) 
def authors = preparedQuery.asList(withLimit(1)) 
assert authors[0].name == "Chris" 

// But I can't find out how to query a collection property eg books on the Author entity 
def query2 = new Query("Author") 
// I would like to do something to return the entity if the value is in the collection property 
// eg if there could be something like 'CONTAINS' criteria ... 
// Unfortunately Query.FilterOperator.CONTAINS doesn't exist... 
query2.addFilter("books", Query.FilterOperator.CONTAINS, b2.key) 
PreparedQuery preparedQuery2 = datastore.prepare(query2) 
def authors2 = preparedQuery2.asList(withLimit(1)) 
assert authors2[0].name == "Chris" 

Come si crea una query che che cerca le partite all'interno di una proprietà della raccolta di un'entità? cioè come ricreare la funzionalità della mitica query "FilterOperator.CONTAINS" sopra?

risposta

6

Rispondere solo per il bene degli utenti che atterrano a questa pagina in futuro:

Query.FilterOperator.EQUAL troveranno all'interno della lista delle chiavi, nonché (funziona come CONTAINS, in caso di liste). Così ora il tuo secondo caso si presenta come:

def query2 = new Query("Author") 
query2.addFilter("books", Query.FilterOperator.EQUAL, b2.key) 
PreparedQuery preparedQuery2 = datastore.prepare(query2) 
def authors2 = preparedQuery2.asList(withLimit(1)) 
assert authors2[0].name == "Chris" 

e passa l'affermazione :)

Questo può sembrare strano a prima vista, ma è davvero una grande caratteristica di DataStore.

3

Un modo per farlo sarebbe avere la chiave dell'autore come uno dei campi nell'entità "Libro". Pertanto, puoi prima interrogare il libro e poi ottenere gli autori per questo.

def author1 = new Entity("Author") 
author1.name = "Chris" 
author1.save() 

def b1 = new Entity("Book") 
b1.title = "Book1" 
b1.authors = [author1.key] 
b1.save() 

author1.books = [ b1.key ] 
author1.save() 

def book = datastore.get(b1.key)  
def chrisAuthors = book.authors.findAll { authorKey -> datastore.get(authorKey).name == 'Chris' } 
assert chrisAuthors.size() == 1 
+0

grazie, speravo che fosse possibile evitare di dover costantemente tenere traccia di e assicurarsi che i riferimenti posteriori siano sincronizzati. Il GAE di Python ha [ReferencePropery] (http://code.google.com/appengine/articles/modeling.html) che mantiene automaticamente coerenti i collegamenti posteriori. Sai se esiste un equivalente Java/Groovy a ReferenceProperty? – Chris

+0

@Chris: se vuoi davvero modellare le relazioni, suppongo che tu debba andare con l'implementazione JDO/JPA di GAE. Tuttavia, non è consigliabile utilizzarli. Non possono completamente astrarre il fatto che BigTable non è un database relazionale. Inoltre, sembrano essere buggy/hacky quando si tratta di relazioni più complesse. Introduce anche nuove dipendenze JAR che aumentano il tempo di avvio dell'applicazione. [Objectify] (http://code.google.com/p/objectify-appengine/) potrebbe invece essere un buon modo per andare. –

Problemi correlati