App Engine数据存储查询结果随机返回
为了更好地理解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);
}
这是结果我得到:
首播时间:第二次:
编辑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);
}
现在的结果是正确
你的实体分类对象应该遵循相同的模式,如果它们都是相同的类型。
创建同一类型,具有相同的父键的不同实体:
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
谢谢,但它没有奏效......请参阅我的编辑。 :( – 2015-04-01 09:33:57
你必须更精确地得出你得到的结果。数据存储最终是一致的,所以如果你在添加数据之后立即查询,这就很正常。 – Patrice 2015-03-31 18:24:20
它看起来像你正在做一个祖先查询,所以你*应该*获得强一致性。你能举一个你看到的例子吗? – tx802 2015-03-31 19:39:00
看我的编辑。我也注意到,当我将'FetchOptions.Builder.withLimit(9)'设置为20时,我得到了20个随机项目,并且有很多重复项目。 – 2015-04-01 09:32:02