2015-03-31 118 views
0

为了更好地理解Datastore的工作原理,我在项目的HttpServlet类中创建了一个包含多个实体和相关属性的数据存储。 创建并填充数据存储之后,我立即查询它以便将Json对象返回给客户端,以便它可以动态更新其UI。App Engine数据存储查询结果随机返回

它的工作原理,但我有一个问题:我第一次查询数据存储后,我总是收到不同的排序结果,往往与重复相同的项目。

这是我的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; 
    } 
} 

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

*编辑*

均匀化实体对象相同类型和设置一个祖先查询,如建议通过@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 

我设置祖先查询:

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

这是结果我得到:

首播时间:first query第二次:second query

编辑2:答案 - 除了执行祖先查询,我还需要申请排序查询。因此,解决方案是将属性添加到每个实体:

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

现在的结果是正确

+2

你必须更精确地得出你得到的结果。数据存储最终是一致的,所以如果你在添加数据之后立即查询,这就很正常。 – Patrice 2015-03-31 18:24:20

+2

它看起来像你正在做一个祖先查询,所以你*应该*获得强一致性。你能举一个你看到的例子吗? – tx802 2015-03-31 19:39:00

+0

看我的编辑。我也注意到,当我将'FetchOptions.Builder.withLimit(9)'设置为20时,我得到了20个随机项目,并且有很多重复项目。 – 2015-04-01 09:32:02

回答

1

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

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

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

+0

谢谢,但它没有奏效......请参阅我的编辑。 :( – 2015-04-01 09:33:57

相关问题