Azure Mobile Service Query Param - android

I have more than one read query.
Query query = QueryOperations
.field("deleted").eq(false)
.select("title", "price", "district","anouncement_id")
.orderBy("announce_from", QueryOrder.Descending)
.skip(countIsLoaded) // counter
.top(5);
Another one is or ecc..
Query query = QueryOperations
.field("deleted").eq(false)
.orderBy("created", QueryOrder.Descending)
.skip(countIsLoaded) // counter
.top(5);
I will have to query using an Andriod Async Task.
Now i have more than one asyntask because i have not find a method to pass the query for Azure Mobile Service. This is the code currently i have
try {
MobileServiceTable<Foo> mToDoTable = MakeEasyApplication.mClient.getTable(Foo.class);
MobileServiceList<Foo> listAnnounce = mToDoTable.where()
.field("deleted").eq(false)
.select("title", "price", "announce_from", "district","anouncement_id")
.orderBy("announce_from", QueryOrder.Descending)
.skip(countIsLoaded)
.top(5)
.execute().get();
for (Foo foo: listAnnounce) {
publishProgress(foo);
}
} catch (Exception e) {
e.printStackTrace();
}
How i can pass the query param instead of having multiple Async Task?

#JoJo, per my experience, I think there are two ways to wrap multiple queries for a async task.
Wrap multiple queries with different query name defined into a function.
public Query getQuery(String qName) {
Query query = null;
switch(qName){
case "QN1":
query = QueryOperations
.field("deleted").eq(false)
.select("title", "price", "district","anouncement_id")
.orderBy("announce_from", QueryOrder.Descending)
.skip(countIsLoaded) // counter
.top(5);
break;
case "QN2":
query = QueryOperations
.field("deleted").eq(false)
.orderBy("created", QueryOrder.Descending)
.skip(countIsLoaded) // counter
.top(5);
break;
//......
default:
//......
}
return query;
}
//In async task
Query query = getQuery("<qName>");
MobileServiceTable<Foo> mToDoTable = MakeEasyApplication.mClient.getTable(Foo.class);
MobileServiceList<Foo> listAnnounce = mToDoTable.where().execute(query).get();
Using Custom APIs, you can define a custom API in the Mobile backend and call the custom API in Android client, then using the name of custom API as parameter instead of having multiple async task.

Related

How to get multiple documents by using where_not_in operator in Firebase Firestore database?

How to get multiple documents from a Collection in firebase if we want to filter using not_in operator with a uniqueId list of documents.
I have a arrayList like this:
ArrayList<String> idList = new ArrayList();
idList.addAll(uniqueIdList);
// now idList have more than 500 uniqueId
Query query = db.collection("my_collection")
.whereEqualTo("status", "DONE")
.whereNotIn("uniqueId", idList)
.orderBy("uniqueId", Query.Direction.DESCENDING)
.orderBy("createdOn", Query.Direction.DESCENDING);
/* FIREBASE DOCUMENTATION SAYS
------------------------------
Use the in operator to combine up to 10 equality (==)
clauses on the same field with a logical OR */
If the idList object have more than 10 items. It crashes the android application due to FirestoreException.
So, should we not use where_not_in operator? But I have specific demand of this for the query.
So, if you want to query using where_not_in operator in Firebase then, you have to do some part from client side also. The query has a serious limitation. So here is a solution.
// Assume idList contains the uniqueId of documents that you don't want
// Assume status can be DONE or PENDING
// Assume list_objects is the ArrayList you have to pass to Recycler view or list view in your app
if (idList.size() > 0 && idList.size() <= 10) {
query = db.collection("my_collection")
.whereEqualTo("status", "DONE")
.whereNotIn("uniqueId", idList)
.orderBy("uniqueId", Query.Direction.DESCENDING)
.orderBy("createdOn", Query.Direction.DESCENDING);
// your on success code here
} else {
query = db.collection("my_collection")
.whereEqualTo("status", "DONE")
.orderBy("createdOn", Query.Direction.DESCENDING);
// here we are fetching all data where status is done
query.get().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
List<Object> list_toRemove = new ArrayList<>();
list_objects = task.getResult().toObjects(ClassName.class);
for (int i = 0; i < list_objects.size(); i++) {
Object item = list_objects.get(i);
if (idList.contains(item.getUniqueId())) {
list_toRemove.add(list_objects.get(i));
}
}
list_objects.removeAll(list_toRemove);
}
}
// remove the data manually here and we are now good. There is no other way for now.
}
So this is a limitation in firebase, but if we look at the advantages of using firebase firestore DB then it's a trade off.
The rule is that if you cannot filter data using query then fetch with applying filters that are possible then again filter using the Collection Framework (if you are using Java). All things are possible in this DB.

How to combine multiple http requests and database query with Rxjava on Android

I need to perform multiple http requests and a database query in order to filter data.
I am usin the zip operator from Rxjava
I did the following to prepare my multiple http requests
List<Observable<List<Picture>>> requests = new ArrayList<>();
for(String id : photoIds) {
requests.add(pictureRepository.searchPicture(id).toObservable());
}
I did the following to prepare my database request
Observable<List<Favourite>> favourites = pictureRepository.getFavourites().toObservable();
I try to create the observable but rxjava is not accepting my code
Observable.zip(
requests, favourites,
new BiFunction<Object[], List<Favourite>, List<FavouritePictures>>() {
#Override
public List<FavouritePictures> apply(Object[] t1, List<Favourite> t2) throws Exception {
return /*here I want to check the favourites and return a list*/;
}
}
);
Is there a way to achieve this?
Thanks
A solution that may work for this is the following:
val photoIds = listOf(1, 2, 3)
var index = 0
Observable.just(0).flatMapSingle {
pictureRepository.searchPicture(photoIds[index])
index += 1
}.repeatUntil {
index + 1 == photoIds.size - 1
}.toList().zipWith(pictureRepository.getFavourites(),
BiFunction { listOfPictures, listOfFavoratePictures ->
// Return your list
})
This observable stream will start by emitting 0;
Then it will flatMap the stream to a Single Observable and return the observable stream from the searchPicture call;
This process will be continued until the last item index has been reached;
Then we map the result to be emitted as one list;
Finally we zip the Single Observable with the getFavourites call;
You could also achieve this using a recursive method but I personally find this more readable.

how to fetch record by pagination using Fetch query and CRMSDK2015 from MS CRM to Android?

by using sdk and fetch query i got 5000 records in one request and it takes too much time for fetch.
please give me suggestion how to get records in page by page using Fetch query and sdk in Android.
Not sure about the Android SDK bit but FetchXML Paging is covered here: Page large result sets with FetchXML
You can try with Linq. Have a look here -
https://msdn.microsoft.com/en-us/library/gg334684.aspx?f=255&MSPPError=-2147217396
You can try this in Query Expression as well:
Page large result sets with QueryExpression
// Query using the paging cookie.
// Define the paging attributes.
// The number of records per page to retrieve.
int queryCount = 3;
// Initialize the page number.
int pageNumber = 1;
// Initialize the number of records.
int recordCount = 0;
// Define the condition expression for retrieving records.
ConditionExpression pagecondition = new ConditionExpression();
pagecondition.AttributeName = "parentaccountid";
pagecondition.Operator = ConditionOperator.Equal;
pagecondition.Values.Add(_parentAccountId);
// Define the order expression to retrieve the records.
OrderExpression order = new OrderExpression();
order.AttributeName = "name";
order.OrderType = OrderType.Ascending;
// Create the query expression and add condition.
QueryExpression pagequery = new QueryExpression();
pagequery.EntityName = "account";
pagequery.Criteria.AddCondition(pagecondition);
pagequery.Orders.Add(order);
pagequery.ColumnSet.AddColumns("name", "emailaddress1");
// Assign the pageinfo properties to the query expression.
pagequery.PageInfo = new PagingInfo();
pagequery.PageInfo.Count = queryCount;
pagequery.PageInfo.PageNumber = pageNumber;
// The current paging cookie. When retrieving the first page,
// pagingCookie should be null.
pagequery.PageInfo.PagingCookie = null;
Console.WriteLine("Retrieving sample account records in pages...\n");
Console.WriteLine("#\tAccount Name\t\tEmail Address");
while (true)
{
// Retrieve the page.
EntityCollection results = _serviceProxy.RetrieveMultiple(pagequery);
if (results.Entities != null)
{
// Retrieve all records from the result set.
foreach (Account acct in results.Entities)
{
Console.WriteLine("{0}.\t{1}\t{2}", ++recordCount, acct.Name,
acct.EMailAddress1);
}
}
// Check for more records, if it returns true.
if (results.MoreRecords)
{
Console.WriteLine("\n****************\nPage number {0}\n****************", pagequery.PageInfo.PageNumber);
Console.WriteLine("#\tAccount Name\t\tEmail Address");
// Increment the page number to retrieve the next page.
pagequery.PageInfo.PageNumber++;
// Set the paging cookie to the paging cookie returned from current results.
pagequery.PageInfo.PagingCookie = results.PagingCookie;
}
else
{
// If no more records are in the result nodes, exit the loop.
break;
}
}

selecting few properties from entity in endpoint point class

I am trying to modify a standard select query in my endpoint class to fetch selected fields from my entity. However even after changing the query, I see that my query result is fetching all the fields. The code is below, you can note that the query has been updated to add my own. I am basically trying to form a query where I only fetch few properties from an entity rather than getting all(to reduce network data transaction volume). Any help is appreciated.
//QUERY MODIFIED IN THIS METHOD
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* #return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listQuizTable")
public CollectionResponse<QuizTable> listQuizTable(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<QuizTable> execute = null;
try {
mgr = getEntityManager();
//Query query = mgr.createQuery("select from QuizTable as QuizTable");
Query query = mgr.createQuery("select n.quizKey, n.quizDesc, n.uploadDate from QuizTable n");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<QuizTable>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (QuizTable obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<QuizTable> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
Projection queries for GAE datastore should serve your purpose. It will return only the required fields in query results and leave the unwanted fields blank. Now to receive this modified response through cloud endpoints, modify your response item representing an individual entity such that it contains only the required fields instead of all the fields in your entity. Then repeat this modified individual response item to create a collection response item.
Projection queries have some limitation on the kind of queries you can do, for example: a field required in the result cannot be used in an equality filter. If you hit such a limitation in your case, then you can use the 2nd option directly without using projection queries. That is, do a normal query and then use the modified individual and collection response items so that they send only the required fields through cloud endpoints.

Better way to write a join query in ormlite

I have two tables CustomerBalance and Customer which are bound with CustomerRefId field.
I want the CustomerBalance records that are lets say greater than 100 for a field balance of this tables. I also want to include into my results the name of the particular customer that fulfills that criteria. I created the following method that works!
public List<CustomerBalance> getCustomerBalanceFilter(String filterVal) {
try {
PreparedQuery<CustomerBalance> preparedQuery = mDbHelper.getCustomerBalanceDao().queryBuilder()
.where().gt(CustomerBalance.DB_COL_CUSTOMER_BALANCE, filterVal)
.prepare();
List<CustomerBalance> result = mDbHelper.getCustomerBalanceDao().query(preparedQuery);
for(CustomerBalance alert : result) {
PreparedQuery<Customer> getCustQuery = mDbHelper.getCustomerDao().queryBuilder()
.where().eq(Customer.DB_COL_CUSTOMER_REF_ID, alert.getCustomerID())
.prepare();
List<Customer> customer = mDbHelper.getCustomerDao().query(getCustQuery);
alert.setCustomer(customer.size() == 1 ? customer.get(0) : null);
}
return result;
} catch(Exception ex) {
return null;
}
}
This methods is working, is this the best way to write such a query? or is there a more appropriate approach?
One improvement to your query is to use ORMLite's SelectArg to pass in the customer-id instead of a new query each time. Something like:
...
List<CustomerBalance> result = mDbHelper.getCustomerBalanceDao()
.query(preparedQuery);
SelectArg custIdArg = new SelectArg();
PreparedQuery<Customer> getCustQuery = mDbHelper.getCustomerDao().queryBuilder()
.where().eq(Customer.DB_COL_CUSTOMER_REF_ID, custIdArg)
.prepare();
for (CustomerBalance alert : result) {
custIdArg.setValue(alert.getCustomerID());
List<Customer> customer = mDbHelper.getCustomerDao().query(getCustQuery);
alert.setCustomer(customer.size() == 1 ? customer.get(0) : null);
}
Here are the docs for SelectArg:
http://ormlite.com/docs/select-arg
FYI, there also is an UpdateBuilder, but I don't see an easy way to turn your code above into a single UPDATE statement.

Categories

Resources