App-engine query - google-app-engine

I am new to app-engine Datastore and to NoSQL world in common. I am developing a simple application where a user can declare his/her expenses everyday. Every user(Account) has its own declared expenses. The dash board contains a simple GWT Cell Tree which contains all the years in which the use declared expenses and when he/she clicks on a years, he gets all the months of the years then he clicks on the month and he gets all the days of the month and finally clicking on a day and he gets all the expenses declared in that day. It is something like
*2010
|_ jan
|_1
|_2
|_Food 12d
|_Dress 200d
|_Fun 150d
|_ ...
|_ feb
|_ ...
*2011
|_ jan
|_ feb
|_...
I save expenses entities in the data store for each user(Account) as the account the parent of all the expenses. my expense is as follow:
public class Expense implements Serializable, Comparable {
private String name;
private double price;
private Date date;
public Expense(String name, double price, Date date) {
this.name = name;
this.price = price;
this.date = date;
}
public Expense() {
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public boolean isPriceValid() {
return price > 0;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#Override
public int compareTo(Expense expense) {
if (name.equals(expense.getName())) {
if (date.equals(expense.getDate())) {
return new Double(price).compareTo(expense.getPrice());
}
return date.compareTo(expense.getDate());
}
return name.compareTo(expense.getName());
}
My QUESTION IS: How to query the expenses in the data store and return all different years relater to a specified Account and put them in a list or set or anything else where I can list them ? does I need to fetch all the expenses entities and iterate over them and get all the different years. doesn't sound reasonable. Any advice will be welcome and THANKS IN ADVANCE.

Several comments related to your post :
--> I wouldn't store a financial amount as a Double. Going that route will lead you to big problems with rounding errors. There are a lot of posts on this one. I would suggest you to store it as "DollarCent" and declare it as an integer. You simply multiply the amount by 100 when you store it and when displaying it you divide by 100.
--> Why do you declare your entity in the Datastore as implementing Serializable ? I would store without Serializable.
--> Related to the specific question on displaying the data by year, reading your question I see no other way than fetching the data. What I would do is ask GAE to order the data to avoid having to order it afterwards. Using Objectify, it would simply be q.filter(...).order(-date).order(amount).
Hope this helps !
Hugues

Related

Anylogic: How to add costs (per route) per time of day?

I have data on different costs per route per time of day for container transport (e.g., from zone A to zone B in the morning; the total costs of transport are 100 euros), for almost 200 zones with 4 times of day. How can I assign these costs in my Anylogic model per route per time of day?
(after this I would like agents (trucks) to decide (based on the costs) which route and time of day to travel)
Given no example data I am using some made-up data to give you an example of how to do this.
Suppose I have the following route and cost data
You can import this into the AnyLogic DB and then use them to populate a custom class with your data.
For example here is a custom Java class for your routes
public class MyRoute {
String id;
String from;
String to;
LinkedHashMap<String, Double> routeCosts = new LinkedHashMap<String, Double>();
/**
* Default constructor
*/
public MyRoute(String id, String from, String to) {
this.id = id;
this.from = from;
this.to = to;
}
public void addCost(String timeOfDay, double cost) {
routeCosts.put(timeOfDay, cost);
}
}
And then I have a little function to populate them from the DB
List<Tuple> rows = selectFrom(routes).list();
for (Tuple row : rows) {
MyRoute route = new MyRoute(
row.get( routes.route ),
row.get( routes.from_db ),
row.get( routes.to_db )
);
// Add costs
List<Tuple> costRows = selectFrom(costs)
.where(costs.route.eq(route.id))
.list();
for (Tuple costRow : costRows) {
route.addCost(
row.get( costs.time_of_day ),
row.get( costs.cost )
);
}
}
Now you can sort the routes based on the costs or time of day and use this to make your decisions
You can see more on sorting here https://www.baeldung.com/java-hashmap-sort

How to format a float number in Jason to show only two decimals?

How to format a number as a currency with two decimals in Jason?
The code bellow illustrates the case:
products([["Banana",1], ["Apple",2], ["Pinapple",2.5]]).
margin(2).
!printPrices.
+!printPrices: products(List) & margin(Z)<-
.length(List,LLenght);
-+listSize(0);
while(listSize(Sz) & Sz < LLenght)
{
.random(Y);
.nth(Sz,List,Item);
.nth(0,Item,Name);
.nth(1,Item,Price);
.print("Product(",Sz,"): ",Name," Price $",Y*Z+Price);
-+listSize(Sz+1);
}.
The output is, I'd like to make the output more readable. Notice that float point numbers have many algharisms.:
[sampleagent] Product(0): Banana Price $1.3689469979841409
[sampleagent] Product(1): Apple Price $2.0475157980624523
[sampleagent] Product(2): Pinapple Price $3.4849443740416803
In fact there is no default internal action in Jason to format it as you want. Howeven, you can create your own Internal Action doing like this:
import jason.asSemantics.*;
import jason.asSyntax.*;
public class formatCurrency extends DefaultInternalAction {
private static final long serialVersionUID = 1L;
#Override
public Object execute(TransitionSystem ts, Unifier un, Term[] args) throws Exception {
StringTerm result = new StringTermImpl(String.format("%.2f", Float.valueOf(args[0].toString())));
un.unifies(result, args[1]);
return true;
}
}
In your agent, you can call this action by:
package_name.formatCurrency(10.5555,Price);

Objectify One-to-Many and Many-To-One in Google App Engine

I'm creating simple backend on Google App Engine using Objectify, that can store Users and thier Recipes.
Model look like this:
User has many Recipes, every Recipe has one author.
I want to be able to:
Get list of Recipes with authors in it
Get list of Users without fetching all recipes
Get one User with all his recipes
According to guide I have done this:
#Entity
public class User {
#Id
private Long id;
#Index
private String name;
List<Recipe> recipes = new ArrayList<>();
/* Other fields */
}
and Recipe :
#Entity
public class Recipe {
#Id
Long id;
String name;
#Index
#Load
Ref<User> author;
/* Other fields */
}
I save Recipe with author (User object) in it.
and 2. requirements work fine,
but when I try to get User with all recipes like this:
public User get(#Named("id") long id) throws NotFoundException {
User user = ofy().load().type(User.class).id(id).now();
if (user == null) {
throw new NotFoundException("Could not find User with ID: " + id);
} else {
List<Recipe> recipes = ofy().load().type(Recipe.class).filter("author", user).list();
account.recipes = recipes;
}
return account;
}
I get empty recipe list.
What am I doing wrong ?
Your author property in your Recipe is a Ref, which is essentially a Key, so you need to filter on that key, like this:
List<Recipe> recipes = ofy().load().type(Recipe.class).filter("author =", Key.create(user)).list();
Incidentally, instead of using .now(), checking for null, then throwing an exception, you could use .safe() which does the same thing for you.

How do I query a single field in AppEngine using JDO

I've got a Product POJO that looks like.
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Product extends AbstractModel {
#Persistent
private String name;
#Persistent
private Key homePage;
#Persistent
private Boolean featured;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Key getHomePage() {
return homePage;
}
public void setHomePage(Key homePage) {
this.homePage = homePage;
}
public boolean isFeatured() {
return featured;
}
public void setFeatured(Boolean featured) {
this.featured = featured;
}
}
My DataStore is currently completely empty.
I'd like to retrieve all homePage keys where featured is true for the Product.
I'm trying
PersistenceManager persistenceManager = getPersistenceManager();
Query query = persistenceManager.newQuery("SELECT homePage FROM " + getModelClass());
query.setFilter("featured == true");
List<Key> productPageKeys = (List<Key>) query.execute();
However this is giving me a null pointer error. How should I be constructing this query?
Cheers,
Peter
To do a projection, you would do something like
Query q = pm.newQuery("SELECT myField FROM mydomain.MyClass WHERE featured == true");
List<String> results = (List<String>)q.execute();
where String is the type of my field. Any basic JDO documentation would define that.
Internally GAE/J will retrieve the Entity, and then in the post-processing before returning it to the user it is manipulated into the projection you require.
As Nick pointed out in the other reply, this gives no performance gain over doing it yourself ... but then the whole point of a standard persistence API is to shield you from such datastore-specifics of having to do such extraction; it's all provided out of the box.
Entities are stored as serialized blobs of data in the datastore, so it's not possible to retrieve and return a single field from an entity. You need to fetch the whole entity, and extract the field you care about yourself.

Need to determine smallest value in a List

I'm stuck at something that seemed easy but became a headache pretty fast:
Here is a class that represent a structure I'm using:
public class LocumJobDistanceDifferenceObject {
public LocumJobDistanceDifferenceObject(Int64 ALocumID, Int64 AJobID, Decimal ADistanceMiles, Int32 ARateDifference, Boolean AIsDistanceUnderMax) {
LocumID = ALocumID;
JobID = AJobID;
DistanceMiles = ADistanceMiles;
RateDifference = ARateDifference;
IsDistanceUnderMax = AIsDistanceUnderMax;
}
public Int64 LocumID {
get;
set;
}
public Int64 JobID {
get;
set;
}
public Decimal DistanceMiles {
get;
set;
}
public Int32 RateDifference {
get;
set;
}
public Boolean IsDistanceUnderMax {
get;
set;
}
}
I create a List to store a matrix of information. Locum is a worker and he needs to be placed at a Job. Lest say I have 50 Jobs and 75 Locums. I build my matrix by running a Locums x Jobs algo that stores LocumID + JobID + Detrmine DistanceMiles between Locum and Job + Determine Rate that Job pays/hour and Locum wants/hour + If dostance to Job exceeds Locum's max distance he/she willing to travel
So, basically, since it's a Locums (75) x Jobs (50) number of rows in the Matrix.
Now, I need to run a loop (ForEach) on my Matrix (I call it MindMapTier01) as follows:
foreach (LocumJobDistanceDifferenceObject LocumJobDistanceDifferenceItem in MindMapTier01.OrderBy(order=>order.JobID)) {
/**
* Build a list (KeyValuePair<JobID, LocumID>) such that for each unique JobID,
* I can assign the Locum closest to that Job. I need to keep in mind that
* once a job is assigned, I dont want that JobID or LocumID for the next iteration
**/
}
I hope I explained myself. I need to get over this within an hour or two. Please help.
Regards.
I don't know that I fully understand your problem, but if you want to ensure that a job is assigned to the closest locum then your code could look like this:
Dictionary<Int64, Int64> dicJobLocum = New Dictionary<Int64, Int64>(); // This is the key value pair list
Dictionary<Int64, Int64> dicJobDistance = New Dictionary<Int64, Decimal>(); // This is to track the distance of the currently assigned locum
foreach (LocumJobDistanceDifferenceObject locum in MindMapTier01) {
if (dicJobDistance.ContainsKey(locum.JobID) {
Decimal distance = dicJobDistance(locum.JobID);
// If the job has been assigned, check if the current locum is closer
if (locum.DistanceMiles < distance) {
dicJobDistance(locum.JobID) = locum.Distance;
dicJobLocum(locum.JobID) = locum.LocumID;
}
}
else {
// If the job has not been assigned yet
dicJobDistance.Add(locum.JobID, locum.DistanceMiles);
dicJobLocum.Add(locum.JobID, locum.LocumID);
}
}
Please excuse any minor syntax errors, I have not been using c# recently.

Resources