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=.


Reply via email to