Here's a video from Google I/O last year about complex data modeling on App Engine. It talks a little bit about how we do indexing underneath the hood:
http://www.youtube.com/watch?v=AgaL6NGpkB8 Look for an upcoming article about the subject. App Engine Datastore is built on top of BigTable. It's not really "voodoo", the properties are simply indexed. The reason it may seem strange is because coming from an RDBMS world, this just isn't something that is done. In App Engine, however, the way indexing works allows us to be flexible in what data types it allows us to surface and the ways we allow users to query those data types. Here are my example classes: Dog.java: http://pastie.org/711953 ListFriendsServlet.java: http://pastie.org/711959 import com.google.appengine.api.datastore.Key; import javax.persistence.*; import java.util.List; import java.util.LinkedList; @Entity public class Dog { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Key key; @Basic private String name; @Basic private int age; private List<Key> dogFriends; public Dog(String name, int age) { this.name = name; this.age = age; } public Dog() { this("Lucky", 5); } public Key getKey() { return key; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void addDogFriend(Key key){ if (this.dogFriends == null) { this.dogFriends = new LinkedList<Key>(); } this.dogFriends.add(key); } public List<Key> getDogFriends(){ return this.dogFriends; } @Override public String toString() { return "Dog{" + "key=" + key + ", name='" + name + '\'' + ", age=" + age + '}'; } } import EMF; import Dog; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import javax.persistence.EntityManager; import javax.persistence.Query; import java.io.IOException; import java.io.PrintWriter; import java.util.List; public class ListFriendsServlet extends HttpServlet { @SuppressWarnings("unchecked") protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String keyString = request.getParameter("friend"); Key key = KeyFactory.stringToKey(keyString); EntityManager em = EMF.get().createEntityManager(); PrintWriter out = response.getWriter(); List<Dog> dogs; try { Query query = em.createQuery("SELECT FROM Dog WHERE dogFriends = :key"); query.setParameter("key", key); dogs = (List<Dog>) query.getResultList(); dogs.size(); // Do this so we can eager load the list and close the EMF } finally { em.close(); } out.println("Listing dogs"); for(Dog dog : dogs) { out.println(dog); } } } The other classes describe adding Dogs and Dog friends and aren't terribly interesting. On Sun, Nov 22, 2009 at 2:49 PM, lp <[email protected]> wrote: > > Can you post the JPA version of your entity? > > @Entity > public class Friend { > > > @Id > @GeneratedValue(strategy = GenerationType.IDENTITY) > private Key key; > > private String lastName; > > public int crud; > > private String firstName; > > @Basic > private Collection<Key> friends; > > > > I've just built something similar, and if I pass a Key to: > > > > query.setParameter("key", key); > > > > This works correctly, though if I pass the String key to it > > > > query.setParameter("key", "someLongString"); > > > what was ur query? was the query to filter on a collection? > i have set the parameters against primitive members successfully but > not against collection members. > > > It returns an empty list. Could this be what is happening? > > no.i just retested my code to make sure i hadnt messed up. i am > definitely using a Key not a string. > > //JPA > javax.persistence.Query query = em.createQuery("select from Friend f > where f.friends=:key"); > query.setParameter("key", user2.getKey()); > > return list of 0 > > using the *same* JPA entity code the JDO works fine > > //JDO > javax.jdo.Query query = pm.newQuery(Friend.class); > Key myKey = user2.getKey(); > query.declareParameters("com.google.appengine.api.datastore.Key > myKey"); > query.setFilter("friends == myKey"); > query.setOrdering("lastName ASC, firstName ASC"); > List<Friend> friendList = (List<Friend>) query.execute(myKey); > > return correct list > > Q1 can u post your JPA code so i can see what u have done differently? > > Q2. is mixing JPA and JDO ok? ie. JPA entity and JDO seems to work for > me. > > Q3.how does the collection equality filter work in app engine? I have > not found any docs to explain the 'voodoo' like behaviour. > from what i can determine the collection filter is executed on the > data store and not in the application as the unfiltered list executed > the 1000 row limit. > it works but i dont understand how. > > any help most appreciated > > -lp > > -- > > You received this message because you are subscribed to the Google Groups > "Google App Engine for Java" group. > To post to this group, send email to > [email protected]. > To unsubscribe from this group, send email to > [email protected]<google-appengine-java%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/google-appengine-java?hl=. > > > -- Ikai Lan Developer Programs Engineer, Google App Engine -- You received this message because you are subscribed to the Google Groups "Google App Engine for Java" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-appengine-java?hl=.
