Compare a date with null value - android

I am showing some posts (created by the users) in an activity using a custom adapter. In the constructor of the custom adapter, I am using the following code to get the query result.
ParseQuery query = new ParseQuery("Post");
query.whereWithinMiles("location_point", my_point, 500);
query.whereGreaterThan("expire_date", new Date());
return query;
The target is - the user can set an expire date with each post so that the post will no longer be visible after the expiration. I am trying to compare the expire_date column with current time for checking if the post is expired or not.
The line query.whereGreaterThan("expire_date", new Date()); was added later. All the previously created rows has a null value in the expire_date column.
So each time I run the query, all the rows that has a date object in expire_date column are being checked according to the condition. The rows having a null value in expire_date column are never returned.
Note: The expire_date column is not a mandatory field (user can choose to leave it empty during creating a post).
Yes, I can set a default date for all the empty/null fields to compare with the expire date. But I was curious to know if there is a way so that I can either return all the rows having a null value or compare the current time with a null object with the whereGreaterThan condition?

ParseQuery notExpiredPosts = new ParseQuery("Post");
query.whereGreaterThan("expire_date", new Date());
ParseQuery noExpiredDate = new ParseQuery("Post");
query.doesNotExist("expire_date");
ParseQuery expiredDateQuery = ParseQuery.or(notExpiredPosts, noExpiredDate);
ParseQuery query = new ParseQuery("Post");
query.whereWithinMiles("location_point", my_point, 500);
query.whereMatchesKeyInQuery("objectId", "objectId", expiredDateQuery);
return query;
[(NotExpiredPost || NoExpiredDate) & (location_point within 500 mile)]
This is what you want, isn't it?
Hope this helps :)

Related

Querying Firebase based on ServerValue.TIMESTAMP

I have a FireBase back end that has a time stamp like so... there are many of these nodes that are objects that have been pushed.
each node has a time stamp set with ServerValue.TIMESTAMP.
in data model class setting server time
private HashMap<String, Object> timestampCreated;
//set time stamp in constructor when new obj is created
public DataModel(...){
// TIME STAMP
HashMap<String, Object> timestampCreatedObj = new HashMap<String, Object>();
timestampCreatedObj.put("date", ServerValue.TIMESTAMP);
this.timestampCreated = timestampCreatedObj;
}
//getting timestamp
public HashMap<String, Object> getTimestampCreated(){
return timestampCreated;
}
#Exclude
public long getTimestampCreatedLong(){
return (long)timestampCreated.get("date");
}
The above all works fine for insertion in DB and i can retrieve the time.
in another class i want to set a query on a FirebaseListAdapter
setting the query lets say for showing items in last 5 days.
long daysInpast= new Date().getTime() - TimeUnit.MILLISECONDS.convert(5, TimeUnit.DAYS);
Then i set up query
Query queryDays= mDatabaseQuery.child("timestampCreated").orderByChild("date").endAt(daysInpast);
final FirebaseListAdapter<myData> adapterQuery = new FirebaseListAdapter<myData>
(getActivity(), myData.class, R.layout.list_item, queryDays) {//do stuff}
Its my query I'm not sure of, my list is returning empty, If i just use my FirebaseListAdapter without the query passing the DB reference my list populates as expected. I suspect its how data is laid out? he fact my times tap is in a subnode is that an issue?
I've tried just using
Query queryDays= mDatabaseQuery.orderByChild("date").endAt(daysInpast);
also but no vail
any help appreciated
You need to run a query on the location above the children that you want returned, which looks to be the root of your database (please don't post pictures with blurred out text, post the actual JSON as text next time).
If indeed you need the level under the root of your database, you can query for the date with:
DatabaseReference root = FirebaseDatabase.getInstance().getReference();
Query query = root.orderByChild("timestampCreated/date").endAt(daysInPast);

How to fetch data between 2 dates in greenDao database

I have two dates . One is the current date and the other is 30 days back date. So I need to fetch the data between these 2 dates in Green Dao. But I am not getting the result.
MyCode:
Date startRangeDate = new Date();
Date endRangeDate = dateBefore30Days;
QueryBuilder<StructSamePage> qb = UserDao.queryBuilder();
qb.where(UserDao.Properties.dateTime.between(startRangeDate.getTime(), endRangeDate.getTime()));
List<StructSamePage> list = qb.list();
Try swapping dates you pass.
Date startRangeDate = new Date();
Date endRangeDate = dateBefore30Days;
QueryBuilder<StructSamePage> qb = UserDao.queryBuilder();
qb.where(UserDao.Properties.dateTime.between(endRangeDate.getTime(),startRangeDate.getTime() ));
List<StructSamePage> list = qb.list();
Generally between works if left hand side value is smaller than right hand side
The WhereCondition between in GreenDao uses this:
/** Creates an "BETWEEN ... AND ..." condition for this property. */
public WhereCondition between(Object value1, Object value2) {
Object[] values = { value1, value2 };
return new PropertyCondition(this, " BETWEEN ? AND ?", values);
}
So you should just have to change your dates accordingly. Because you are using NOW first and the day 30 days before later your code would do this:
Value >= NOW AND Value <= 30 DAYS BEFORE
If you use actual dates wich greenDAO does not use! Your code would look like this:
today = 2016-03-04
30DaysAgo = 2016-02-03
WHERE dateTime >= 2016-03-04 AND dateTime <= 2016-02-03
So you should be fine if you just change your order.
If you want to know more about how BETWEEN works you can read this
A word of advice: greenDao uses timestamps as INTEGERS in the database so if you use java Dates you get a Date that also has a time (when it was created) if you just remove 30 days from it you will not include the whole day 30 days ago but only the day from the time the current date object was created in time. So maybe you want to create the Date from a Calendar without a time.

Eliminating range key criteria for Dynamo Update query?

How can I get Dynamo's UpdateItemRequest to either ignore the range key, or do a coarse test such as not null?
I am using a range key which contains the time of a record update. Separately, I update rows which I select using an ID field which is not a key. I update the ID field using an expectedAttribute in an UpdateItemRequest. Dynamo's UpdateItemRequest forces me to specify a range key value. My ID update code will not know the range key value. Can I somehow not specify a range key and not get an error? Or can I provide a simple range key test like not null?
When I remove the range key, AWS throws an error, "The provided key element does not match the schema"
// construct the update map
HashMap<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
AttributeValue av = new AttributeValue().withN("1");
AttributeValueUpdate avu = new AttributeValueUpdate().withValue(av).withAction(AttributeAction.PUT);
updates.put("Column1", avu);
AttributeValue av2 = new AttributeValue().withN("2");
AttributeValueUpdate avu2 = new AttributeValueUpdate().withValue(av2).withAction(
AttributeAction.PUT);
updates.put("Column2", avu2);
// construct the key map
HashMap<String, AttributeValue> keyMap = new HashMap<String, AttributeValue>();
AttributeValue hashValue = new AttributeValue().withN("10");
keyMap.put("hashKey", hashValue);
AttributeValue lastModKeyValue = new AttributeValue().withN("1404175127074");
// ****** I want to remove this key but Dynamo throws an error
keyMap.put("problemRangeKey", lastModKeyValue);
// expected value comparison
AttributeValue idValue = new AttributeValue().withN("100");
ExpectedAttributeValue expected = new ExpectedAttributeValue(idValue);
UpdateItemRequest request = new UpdateItemRequest().withTableName(DatabaseConstants.CHART_TABLE)
.withKey(keyMap).withAttributeUpdates(updates).addExpectedEntry(ID, expected);
ddb.updateItem(request);
For clarity, here is how I use the range key to find rows after a specific time. If I remove this time range, then I would do a big scan every time to find rows after a specific time.
Map keyConditions = new HashMap();
AttributeValue attribute = new AttributeValue().withN("10");
Condition hashKeyCondition = new Condition().withComparisonOperator(ComparisonOperator.EQ.toString())
.withAttributeValueList(attribute);
keyConditions.put("hashKey", hashKeyCondition);
// specify new records
long lastQueryTime = PrefsActivity.getLastDynamoQueryTime(activity);
String lastTimeString = String.valueOf(lastQueryTime);
Log.v(TAG, "get Charts from dynamo that are after " + lastTimeString);
// update the query time to now
long now = System.currentTimeMillis();
PrefsActivity.setLastDynamoQueryTime(activity, now);
AttributeValue timeAttribute = new AttributeValue().withN(lastTimeString);
Condition timeCondition = new Condition().withComparisonOperator(ComparisonOperator.GT.toString())
.withAttributeValueList(timeAttribute);
keyConditions.put("problemRangeKey", timeCondition);
List<Map<String, AttributeValue>> ChartsInMaps = new ArrayList<Map<String, AttributeValue>>();
Map lastEvaluatedKey = null;
QueryRequest request = new QueryRequest().withTableName("tableName")
.withKeyConditions(keyConditions).withExclusiveStartKey(lastEvaluatedKey);
QueryResult result = ddb.query(request);
I'm working with the latest AWS Android SDK. In the sample above, I'm setting the hashKey to "10". In practice, that will vary.
Thanks in advance for any help!
Jeff
The question is, you want to update all items with a specific hashKey value and a specific column value (column name is id).
The table is Hash-Range schema. Since you don't know the range key, you have to fetch all the rows with that hashKey and then do a filter based on the column value (ID == value). You can use query filter to do that efficiently. Then for each row in your query, do a conditional put with expected value (ID == value) just to be sure.
QueryRequest request = new QueryRequest();
// set up query request (table name, etc)
// set up query filter (ID == value)
QueryResponse response = client.query(request)
for (item in response.items):
PutItemRequest req = new PutItemRequest();
// set up put item request
// set up primary key for item to update
// hashkey = item.hashkey
// rangekey = item.rangeKey
// set up expected value (ID == value)
client.updateItem(req)
On the other hand, since you want to efficiently query all the rows after a specific time, you can create a Local Secondary Index with "time" as a range key instead of making "time" the range key of your base table. You can still do efficient query using LSI (compared with scanning the table and filter by time). Whats more important is, if your "ID" attribute can uniquely identify a row with your hashkey, you can make "ID" the range key of your base table. This way you can also update the item efficiently since you already know the hashkey value and range key value (id value).
Of course it only truly benefits you when your hashkey and "ID" can uniquely identify a row :)

SQL MAX-MIN in ORMLITE - ANDROID

I want to know how can i use MAX MIN command with ORMLITE.
For example lets say we have this table
Table Name = Example
Column 1 = id
Column 2 = name
In ORMLITE how can i get max id ? I looked here but i didnt't understand exactly..
Can someone show me example about Max min in ORMLITE ?
QueryBuilder<Account, Integer> qb = accountDao.queryBuilder();
qb.selectRaw("MIN(orderCount)", "MAX(orderCount)");
// the results will contain 2 string values for the min and max
results = accountDao.queryRaw(qb.prepareStatementString());
String[] values = results.getFirstResult();
I found this from documentation
This is how I query for max ID in my code:
QueryBuilder<Example, String> builder = dao.queryBuilder();
builder.orderBy("id", false); // true or false for ascending so change to true to get min id
Example example = dao.queryForFirst(builder.prepare());
String id = null;
if (example == null)
id = "-1";
else
id = example.getId();
A couple of alternative answers can also be found here:
ORMLite - return item w/ maximum ID (or value)
You can use:
dao.queryRawValue("select MAX(columnName) from tableName")
It will directly return long value.
refer: http://ormlite.com/javadoc/ormlite-core/doc-files/ormlite_5.html#DAO-Methods
queryRawValue(String query, String... arguments)
Perform a raw query that returns a single value (usually an aggregate function like MAX or COUNT). If the query does not return a single long value then it will throw a SQLException.

Ormlite orderBy max(ColumnName)

Hi I need to use order by max(columnName) in ORMLite. I have the SQL query but I need to know how this query is used. This is my query:
SELECT * FROM table where place = 'somePlace' group by name
order by MAX (statusDate)
statusDate column contains date in "yyyy-dd-mm" format. The result I got is the list with recentDates.
Use a query builder, and function where and orderBy to preoceed
QueryBuilder<YourObject, Integer> q = yourDaoObject.queryBuilder();
Where<YourObject, Integer> wh = q.where();
wh.eq("place", "some_place");
q.orderBy("statusDate", false);
List<YourListOfObects> yourList = q.query();
But before that you should store a long instead to store your Date https://stackoverflow.com/a/6993420/2122876
i got same names with different dates and i need only the recent date.
If you are trying to get element from Table with the maximum statusDate then you should be doing an descending order-by with a limit of 1. Something like:
QueryBuilder<Foo, Integer> qb = fooDao.queryBuilder();
qb.where().eq("place", "some_place");
qb.orderBy("sttusDate", false); // descending sort
// get the top one result
qb.limit(1);
Foo result = qb.queryForFirst();
I did something like this. Please create your own query builder on the first line.
QueryBuilder<MyRowObject, Integer> queryBuiler = "Get Query builder" //getDaoXXX().queryBuilder();
MyRowObject firstLatestRow = queryBuiler.orderBy("dateColoumn", false).queryForFirst();
Hope this helps

Categories

Resources