2013-01-13 12 views
21

Esistono due tipi di entità: Utente e Viaggio. L'utente è genitore di Trip and Trip è child to User.Datastore del Google App Engine: come ottenere entità per ID/Nome se la chiave genitore è sconosciuta?

Per considerazioni sulla privacy, sto postando solo ID viaggio/nome. Perché sembra che una chiave di viaggio contenga l'ID/nome utente codificato.

Come ottenere l'entità per ID/Nome se la chiave genitore è sconosciuta?

+2

+1 - questa è una domanda perfettamente valida. Chiunque metta -1 - cura di spiegare? –

+1

Perché non usi la ricerca? [vedi] [1] [1]: http://stackoverflow.com/questions/12675664/create-a-good-looking-url-for-a-key-with-ancestors/12676004#comment17106761_12676004 –

+1

@ Lapteuh - Hai visto anche la risposta a cui ti stai riferendo? La query che propongono richiede la chiave genitore completa (tipo + id/nome) e questo è esattamente ciò che l'OP non ha. –

risposta

17

Non è possibile. La chiave principale è parte della chiave dell'entità e hai bisogno di una chiave completa per ottenere un'entità.

Anche query with key filter non troverà le entità con i genitori a meno che non si specifichi la chiave dell'antenato.

0

@ peter-knego Nella domanda iniziale: l'utente è il genitore di Trip. Per ottenere entità per id è necessario ricostruire la chiave con il genitore per ottenere la chiave completa. Ma puoi evitarlo, basta assegnare gli id ​​per la chiave completa di Trip. E tu puoi costruire la chiave piena con id assegnato. Questa è la mia logica.

1

Se si creano tutte le entità "Utente" sotto un'entità "Root" e si aggiunge una proprietà "uuid" all'entità "Trip", è possibile cercare il singolo "Trip" con l'UUID specificato.

Filter uuidFilter = new FilterPredicate("uuid", FilterOperator.EQUAL, uuid.toString()); 
Query q = new Query("Trip").setAncestor(root.getKey()).setFilter(uuidFilter); 
0

si può fare qualcosa di simile:

public Entity GetEntity(String kind, String idName) 
     throws EntityNotFoundException{ 
    Key key = KeyFactory.createKey(kind, Long.parseLong(idName)); 
    return datastore.get(key); 
} 
+1

No, non troverà nulla a meno che non si specifichi il genitore in 'chiave'. –

0

ho lavorato fuori 3 alternative che possono risolvere questo problema, che è molto importante IMHO.

---- prima alternativa ----

Se l'identificativo del tuo viaggio viene calcolata in un altro attributo, c'è un modo. Invece di ottenere il Trip dal suo id ottenerlo da quell'altra proprietà calcolata. Immaginiamo che l'id del tuo viaggio sia calcolato con un nome canonico (A URN tu intuisci dal suo titolo completo), ad es. se il nome completo del viaggio è

Viaggio Everest

tuo nome canonico potrebbe essere voyage-to-the-everest e questa è la stringa si usa come nome per la chiave. Così, invece di ottenere l'elemento utilizzando datastore.get uso:

@Override 
public Optional<Trip> findById(String tripCanonicalName) { 
    StructuredQuery.PropertyFilter eqTripCanonicalName = StructuredQuery.PropertyFilter 
        .eq("canonicalName", tripCanonicalName); 

    EntityQuery query = Query.newEntityQueryBuilder().setKind("Trip") 
        .setFilter(eqTripCanonicalName).setLimit(1).build(); 

    QueryResults<Entity> results = getDatastoreService().run(query); 

    if (results.hasNext()) { 
     return Optional.of(fromEntity(results.next())); 
    } 

    return Optional.empty(); 
} 

questo otterrà l'entità (Trip) non importa il cui padre (User) essere.

---- seconda alternativa ----

Prima di accedere a un elemento probabilmente è necessario prima di elencarli, quindi selezionare uno e andare a un collegamento di accesso. Come sappiamo utilizzando l'id del compito wont essere sufficiente perché sarà unico solo per il suo genitore (User), ma invece di mostrare che id è possibile utilizzare l'url id sicura:

entity.getKey().toUrlSafe() 

così nella conversione da entità a oggetto assegnare l'elemento Task questo ID codificato in un base-64 encode.Per recuperare la chiave dall'URL sicuro

Key.fromUrlSafe 

Garantirà che userete sempre un ID univoco globale.

---- 3 ° alternativa ----

Usando HATEOAS è possibile specificare il link per il accesing Task, quindi se l'attività ha qualche id come parentId o userId che è fondamentalmente ottenere il suo genitore id del nodo, potrebbe essere molto facile per voi può fortificare un link che punta a un URL come questo

http://base-url.com/users/ {userid}/attività/{} taskId

Quindi, in una richiesta hateoas questo potrebbe sia indicata nei collegamenti, che indica le azioni consentite per l'elemento, quindi per la visualizzazione dell'elemento utilizzare self, ad esempio

{ 
    "id": "voyage-to-the-everest", 
    "name":"Voyage to the Everest", 
    "userId": "my-traveler-user-id", 
    "_links":{ 
    "self":{ 
     "href":"http://localhost:8080/users/my-traveler-user-id/tasks/voyage-to-the-everest 
    } 
    } 
} 

Se invece di un userId si utilizza un parentId si può lavorare fuori con un'interfaccia in cui tutto i nodi specificano se hanno un genitore o no. Anche potrebbe essere più flessibile con una proprietà parent in cui si definisce l'intera gerarchia padre:

public interface DatastoreNode{ 
    String getParentId(); 
    String getParentKind(); 
    String getParentUrlTag(); 
    DatastoreNode getParent(); 
} 

Anche se hateoas è fortemente consigliato è possibile dedurre lo stesso URL con una struttura JSON come

{ 
     "id": "voyage-to-the-everest", 
     "name":"Voyage to the Everest", 
     "parent": { 
      parentKind: "User", 
      parentId: "my-traveler-user-id", 
      parentUrlTag: "users", 
      parent: {} 
     } 
    } 
Problemi correlati