App Engine Datastore 查询结果随机返回

App Engine Datastore query result is returned randomly

为了更好地理解数据存储的工作原理,我在项目的 HttpServlet class 中创建了一个具有多个实体和相关属性的数据存储。 创建并填充数据存储后,我立即查询它以便 return 一个 Json 对象返回给客户端,以便它可以动态更新其 UI。

它有效,但我有一个问题:在我第一次查询数据存储后,我总是收到排序不同的结果,通常是相同项目的重复项。

这是我的 HttpServlet 代码:

public class MyServlet extends HttpServlet {
    ArrayList<Tour> m_tours = new ArrayList<Tour>();
    Key tourKey;
    DatastoreService datastore;
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
        //nothing special here
    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        populateDatastore();

        String asyncMessage = req.getParameter("order");
        if(asyncMessage.equals("tours")){
            m_tours = getTours();
        }
        if(asyncMessage.equals("selectTour")){

        }

        Tours tours = new Tours(m_tours);
        resp.setContentType("application/json");
        PrintWriter out = resp.getWriter();
        out.print(new Gson().toJson(tours));
        out.flush();
    }
    private DatastoreService populateDatastore(){

    datastore = DatastoreServiceFactory.getDatastoreService();
    tourKey = KeyFactory.createKey("availabletours", "tours"); //parent

    Entity tour = new Entity("tour", tourKey);
    tour.setProperty("tourname", "Tour0");
    tour.setProperty("tourinfo", "info0");
    datastore.put(tour);

    Entity tour1 = new Entity("tour1", tourKey);
    tour1.setProperty("tourname", "Tour 1");
    tour1.setProperty("tourinfo", "info 1");
    datastore.put(tour1);

    //..... and so on

    return datastore;
}

private ArrayList<Tour> getTours(){
    ArrayList<Tour> toursArray = new ArrayList<Tour>();

    Query query = new Query(tourKey);
    List<Entity> tourss = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(9));
    for (Entity t : tourss) {
        String tourname=t.getProperty("tourname").toString();
        String tourinfo=t.getProperty("tourinfo").toString();
        Tour ts = new Tour(tourname,tourinfo);
        toursArray.add(ts);
    }

    return toursArray;
    }
}

我做错了什么?管理数据存储的最佳方式是什么?

* 编辑 *

After uniforming the Entity objects to the same type and setting an ancestor query, as suggested by @Jeff Deskins:

    datastore = DatastoreServiceFactory.getDatastoreService();
    tourKey = KeyFactory.createKey("availabletours", "tours"); //parent

    Entity tour = new Entity("tour", tourKey);
    tour.setProperty("tourname", "Tour0");
    tour.setProperty("tourinfo", "info0");
    datastore.put(tour);

    Entity tour1 = new Entity("tour", tourKey);
    tour1.setProperty("tourname", "Tour 1");
    tour1.setProperty("tourinfo", "info 1");
    datastore.put(tour1);

    //... ...  same way with the others

I set an ancestor query:

    Query query = new Query("tour").setAncestor(tourKey);
    List<Entity> tourss = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(9));
    for (Entity t : tourss) {
        String tourname=t.getProperty("tourname").toString();
        String tourinfo=t.getProperty("tourinfo").toString();
        Tour ts = new Tour(tourname,tourinfo);
        toursArray.add(ts);
    }

这是我得到的结果:

第一次:第二次:

EDIT 2: Answer - Apart from performing an ancestor query, I also needed to apply a Sort to the Query. Therefore the solution is to add a property to each entity:

  Entity tour = new Entity("tour", tourKey);
        tour.setProperty("tourname", "Tour 1");
        tour.setProperty("tourinfo", "info 1");
        tour.setProperty("order","0");
  Entity tour = new Entity("tour", tourKey);
        tour.setProperty("tourname", "Tour 2");
        tour.setProperty("tourinfo", "info 2");
        tour.setProperty("order","1");

然后对查询应用排序过滤器:

    ArrayList<Tour> toursArray = new ArrayList<Tour>();

    Query query = new Query("tour").setAncestor(tourKey).addSort("order");
    List<Entity> tourss = new ArrayList<Entity>();
    tourss = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());

    for (Entity t : tourss) {
        String tourname=t.getProperty("tourname").toString();
        String tourinfo=t.getProperty("tourinfo").toString();
        Tour ts = new Tour(tourname,tourinfo);
        toursArray.add(ts);
    }

现在结果已正确排序

如果实体对象都是同一类型,则它们应遵循相同的模式。

创建具有相同父键的相同类型的不同实体:

Entity tour1 = new Entity("Tour", tourKey);
Entity tour2 = new Entity("Tour", tourKey);

将上述对象填充并保存到数据存储区后,您可以通过以下方式查询:

Query tourQuery = new Query("Tour")
                         .setAncestor(tourKey);

祖先查询提供强一致性。 https://cloud.google.com/appengine/docs/java/datastore/queries#Java_Ancestor_queries