Reputation: 2021
As an exercise to better understand how the Datastore works, I have created within the HttpServlet class of my project a datastore with several entities and relative properties. After creating and populating the datastore, I immediately query it in order to return a Json object back to the Client so it can dynamically update its UI.
It works, but I have a problem: after the first time I query the datastore, I always receive a result ordered differently, often with duplicates of the same items.
This is my HttpServlet code:
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;
}
}
What am I doing wrong? What is the best way to manage a datastore?
* EDIT *
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);
}
And this is the result I get:
First time: Second time:
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");
and then apply a sort filter to the query:
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);
}
now the result is sorted properly
Upvotes: 0
Views: 157
Reputation: 1660
Your Entity objects should follow the same pattern if they are all the same type.
Creating different entities of same type with same parent key:
Entity tour1 = new Entity("Tour", tourKey);
Entity tour2 = new Entity("Tour", tourKey);
After populating and saving the above objects to the datastore, you can then query by:
Query tourQuery = new Query("Tour")
.setAncestor(tourKey);
The ancestor query provides strong consistency. https://cloud.google.com/appengine/docs/java/datastore/queries#Java_Ancestor_queries
Upvotes: 1