2013-01-13 5 views
21

Istnieją dwa rodzaje encji: użytkownik i podróż. Użytkownik jest rodzicem na Trip a Trip jest dzieckiem dla Użytkownika.Google App Engine Datastore: Jak uzyskać encję według identyfikatora/nazwy, jeśli klucz rodzica jest nieznany?

Ze względu na ochronę prywatności wysyłam tylko identyfikator/nazwę podróży. Ponieważ wygląda na to, że klucz podróży zawiera zakodowany identyfikator/nazwę użytkownika.

Jak uzyskać encję według identyfikatora/nazwy, jeśli klucz rodzica jest nieznany?

+2

+1 - to doskonale słuszne pytanie. Kto udzielił -1-opieki, aby wyjaśnić? –

+1

Dlaczego nie korzystasz z wyszukiwania? [see] [1] [1]: http://stackoverflow.com/questions/12675664/create-a-good-looking-url-for-a-key-with-ancestors/12676004#comment17106761_12676004 –

+1

@ Lapteuh - Czy spojrzałeś nawet na odpowiedź, której dotyczysz? Zapytanie, które proponuje, wymaga pełnego klucza nadrzędnego (rodzaju + id/nazwy) i właśnie to OP nie ma. –

Odpowiedz

17

Nie możesz. Klucz rodzica jest częścią klucza encji i potrzebny jest pełny klucz, aby uzyskać encję.

Również query with key filter nie znajdzie elementów z rodzicami, chyba że określisz klucz przodka.

0

@ peter-knego W pytaniu początkowym: Użytkownik jest rodzicem w podróży. Aby uzyskać encję po identyfikatorze, musisz zrekonstruować klucz z rodzicem, aby uzyskać pełny klucz. Ale możesz tego uniknąć, po prostu przydzielaj identyfikatory dla pełnego klucza podróży. Możesz też skonstruować pełny klucz z przydzielonym identyfikatorem. To jest moja logika.

1

Jeśli utworzysz wszystkie jednostki "Użytkownika" w jednostce "Root" i dodasz właściwość "uuid" do encji "Trip", możesz poszukać pojedynczego "Trip" z określonym UUID.

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

można zrobić coś takiego:

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

Nie, nie znajdzie niczego, chyba że określisz rodzica w 'key'. –

0

wypracowałem 3 alternatywy, które mogą rozwiązać ten problem, który jest bardzo ważny IMHO.

---- 1-ta alternatywa ----

Jeśli podróż identyfikator jest obliczany z innego atrybutu, istnieje sposób. Zamiast pobierania Trip przez jego id uzyskać z tej innej obliczonej właściwości. Wyobraźmy sobie, że identyfikator Twojej podróży jest obliczany na podstawie pewnej nazwy kanonicznej (A URN, którą wyprowadzasz z pełnego tytułu), np. jeśli pełna nazwa TRIP jest

Voyage do Everest

Twoja nazwa kanoniczna może być voyage-to-the-everest i to jest String użyć jako nazwę dla klucza. Więc zamiast się element używając datastore.get zastosowanie:

@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(); 
} 

to dostanie jednostki (Trip) bez względu na to, którego rodzic (User) być.

---- 2-ta alternatywa ----

Przed wejściem elementu prawdopodobnie najpierw trzeba je wymienić, a następnie wybrać jedną i przejdź do łącza dostępowego. Jak wiemy z wykorzystaniem identyfikatora zadania przyzwyczajenie wystarczy, ponieważ będzie to unikalna tylko dla jego rodzica (User), ale zamiast pokazywać, że id można użyć bezpiecznego identyfikatora URL:

entity.getKey().toUrlSafe() 

więc w konwersji od obiektu do obiektu przypisz element Task, którego identyfikator jest zakodowany w base-64 encode.Aby odzyskać klucz z bezpiecznego adresu URL, należy użyć tej opcji, aby zagwarantować, że zawsze będziesz używał globalnego unikalnego identyfikatora.

---- 3-cie alternatywa ----

Korzystanie HATEOAS można podać link do accesing się Task, więc jeśli zadanie ma jakiś identyfikator taki jak parentId lub userId który jest w zasadzie uzyskanie jego rodzica ID węzła, to może być bardzo łatwo można utwierdzi się link wskazujący url jak ten

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

więc we wniosku hateoas to może wskazuje się w linki, które wskazuje dozwolony działania dla elementu, więc do oglądania wykorzystywać element self np

{ 
    "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 
    } 
    } 
} 

Jeśli zamiast userId używasz parentId można się dogadać z interfejsem gdzie wszystko węzły określają, czy mają rodzica, czy nie. Nawet to może być bardziej elastyczna z parent nieruchomości, gdzie można zdefiniować całą hierarchię nadrzędny:

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

Chociaż hateoas Zaleca można wywnioskować tej samej zawartości mający strukturę json takich jak

{ 
     "id": "voyage-to-the-everest", 
     "name":"Voyage to the Everest", 
     "parent": { 
      parentKind: "User", 
      parentId: "my-traveler-user-id", 
      parentUrlTag: "users", 
      parent: {} 
     } 
    } 
Powiązane problemy