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
为了更好地理解数据存储的工作原理,我在项目的 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