Does using SnapshotParser while querying Firestore an expensive operation in terms of read operation?
We are building query in our app like this:
options = new FirestoreRecyclerOptions.Builder<Item>()
.setQuery(query, new SnapshotParser<Item>() {
#NonNull
#Override
public Item parseSnapshot(#NonNull DocumentSnapshot snapshot) {
Item item = snapshot.toObject(Item.class);
item.setId(snapshot.getId());
return item;
}
})
.setLifecycleOwner(this)
So while reading data from server, does SnapshotParser will make extra read operation (or hit server again) or it will parse using already read data?
Would it be the same operation(in terms of server hit) with or without SnapshotParser?
Please explain, if anything is missed, please let me know? Sorry for bad english.
From the official documentation of Firebsase-UI library:
If you need to customize how your model class is parsed, you can use a custom SnapshotParser.
So if you need to customize your model class it doesn't mean that you are creating extra read operations. The parseSnapshot() method uses as an argument a DocumentSnapshot object which contains the data set that you are getting from the database for which you are already charged in terms of read operations. This is happening if the the query return data. If your query does not return any data, you are still charged but only with a single read operation.
Related
I've created my first Play Framework Website with Java using the official documentation. It has a single page where I display a list of items that can be filtered or modified.
I have a Controller class with a method:
public CompletionStage<Result> feedpostslist(String domain, String date, String state, int page, int resnum, String search) {
return feedRepository.getArticleList(domain, date, state, page, resnum, search).thenApplyAsync(articles -> {
FeedArticle[] list = new FeedArticle[articles.size()];
articles.toArray(list);
return ok(views.html.feedpostslist.render(list));
}, ec.current());
}
This method does a query to the DB (through feedRepository) and then display the result using the view feedpostslist.
Everything is fine but now I need to get other data from the DB to be used in the same web page (so multiple queries). How do I do this in Play Framework? I don't understand what is the best way to do that.
Should I do multiple DB request inside the method showed before (through feedRepository) and then pass all these informations to my view? I don't want to do a mess or even something too heavy to handle.
If the second query doesn't depend on the first one you can run them in parallel using combineAsync. This is a good example on how to do that:
https://github.com/playframework/play-samples/blob/2.8.x/play-java-ebean-example/app/controllers/HomeController.java#L85
If the second query depends on results on the first then there's nothing you can do but to wait for the first one to complete and run the second one.
I have a collection who contains items of a restaurant menu, i want to know when a new item is added or have a change(price, name, description), because i want to notify this to the app and download this changes in a internal database.
I was trying to create a firebase function to modify a field called version and this way campare version in the app vs firebase version of the collection but i really dont know how to work with firebase functions.
can someone give a recomendation?
Cloud Firestore is a flexible, scalable database which keeps your data in sync across client apps through realtime listeners and offers offline support for mobile and web applications.
So in order to know if something has been changed in your database, you need to attach a listner on a particular location. Assuming you have a collection named cities and a document named SF, plase use the following code. It's a straight forward example.
DocumentReference docRef = db.collection("cities").document("SF");
docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot snapshot, #Nullable FirebaseFirestoreException e) {
// see which fields changed
}
});
Unlike Firebase Realtime database, Cloud Firestore has data persistence enabled by default. So there is no need to keep your data also in a internal database.
I use the Parse.com Cloud service in my Android app to sync data between devices.
I use the app mainly offline and use the local data store.
There is one class called Point that has a unique number as identifier I want to display. So when working offline I want to create a Point as draft (with a draft text as number) and when synchronizing I want it to get the real number that is unique over all the devices.
How would I set the number when saving? I was thinking about adding a WebHook in the cloud when saving the Point and giving it a unique number and then in my app use
newPoint.saveEventually(new SaveCallback() {
public void done(ParseException e) {
//query for the number
}
});
to query the point from the cloud to get the number after it has been saved. But this seems kind of too complicated for such a simple requirement. And I am not sure if the SaveCallback() is always triggered when saving it.
I would recommend using an afterSave trigger on the Point class to set the unique identifier when the object is newly created. Then, as you've mentioned, you'll need to fetch the value before displaying it.
Here's what the cloud code could look like:
// Assign the Point a unique identifier on creation
Parse.Cloud.afterSave("Point", function(request) {
// Check if the Point is new
if (!(request.object.existed())) {
// Get the unique identifier
var uniqueIdentifier = ...
// Set the unique identifier
request.object.set('uniqueIdentifier', uniqueIdentifier);
}
});
One important bit of information to keep in mind about using saveEventually with SaveCallback() is:
The callback will only be called if the operation completes within the
current app lifecycle. If the app is closed, the callback can't be
called, even if the save eventually is completed.
Source: Hector Ramos
If the unique identifier should be immediately displayed in the app or if the callback needs to be handled consistently, it would probably be best to use saveInBackground rather than saveEventually.
Another option would be to dynamically change the callback depending on network availability and/or offline settings. For example, if the offline mode is used anytime when the cell signal or wifi is unavailable, then network reachability could be used to check for a network and then use saveInBackground or saveEventually as appropriate.
Update
OP ended up using this code:
Parse.Cloud.beforeSave("Point", function(request, response) {
if (!(request.object.existed())) {
var query = new Parse.Query("Point");
query.addDescending("uniqueIdentifier");
query.first({
success: function(result) {
var maxId = result.get("uniqueIdentifier");
request.object.set("uniqueIdentifier", maxId + 1);
},
error: function() {
}
});
}
response.success();
});
I have a trouble, i need to get event/callback when i try to write to database.
I added greenDao lib to project, and i able to write/delete in db.
But no idea how to get callback after some operation under db.
In introduction to lib i read "AsyncOperationListener for asynchronous callback when operations complete".
Used this tutorial:
http://blog.surecase.eu/using-greendao-with-android-studio-ide/
Can anybody help me with this trouble?
UPD:
ok here we added some list in storage
getMyObjectDao().getSession().startAsyncSession().insertOrReplaceInTx(MyObject.class, list);
error here
List<MyObject> items = getBoxDao(c).getSession().startAsyncSession().loadAll(MyObject.class);
How can we asynchronously load data from db?
Is this correct solution?
#Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
String operationIs = null;
switch (operation.getType()) {
case LoadAll:
itemsList = BoxRepository.getAllBoxes(getApplicationContext());
By default all the operations are performed synchronously, eliminating the need to get any callback. But the recent version of GreenDAO introduces AsyncSession, which can be used to perform operations asynchronously and also provides a way set listener on it. See the example below:
AsyncSession asyncSession = App.getInstance().daoSession.startAsyncSession();
asyncSession.setListener( new AsyncOperationListener() {
#Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
// do whats needed
}
});
asyncSession.insert(MyObject);
Simple ask if anything unclear!
I am newbie on GWT. I am writing the code of a page which asks a JSON object that contains two collections and I use one of these collection to fill a Flextable.
This is my JSON Object:
public class Users extends JavaScriptObject {
protected Users() {
}
public final native JsArray<Link> getLinks() /*-{
return this.links;
}-*/;
public final native JsArray<User> getCollection() /*-{
return this.collection;
}-*/;
}
In particular I am using the second collection (called collection) to fill a Flextable. But my problem is that when I delete one row from the table, even if I send a request with an http delete method to the server (and the server delete that item successfully), when I try to refresh the table GWT does not generate the GET request to the server, (even if it is written in the code) and Users Object is the same as before with the deleted item also.
I have tried to delete this item from collection using this method:
public static native void remove(JsArray<?> arr, int index, int count) /*-{
arr.splice(index, count);
}-*/;
....
remove(users.getCollection(), index, users.getCollection().length());
And I also tried this other technique:
users.getCollection().set(index, null);
But in both cases, I do not get the expected result, when I refresh the table I find the deleted items again.
I think that I am not managing the DOM properly, Do you have any suggestions? Any Idea? I am sure it is simple problem to solve for an expert.
EDIT:
The user can refresh the data in the table clicking a button, the handler of this event will perform a request to a server, but this request is sent on the first click only.
Basically there are two alternatives, the first is to set the header Cache Control to no-cache in the server side, while if you cannot modify the code in the server side, for example in the case of legacy applications, you can attach a random number in your request in a parameter. A request will have a uri with an additional parameter which is a random generated number, http:\\mydomain.com\something?random=12345. Two different requests will have different numbers and at the second request the response of the first request, which has been cached it will be ignored. It is not a smart practice, but it works.
For getting data like this better use HTTP POST request, because GET requests are being cached (by GWT, proxy servers...).
Also make sure your server code for deleting items is doing right job, and manually check server response in firebug or in chrome console to see if your response contains deleted records.
Please post code you use to fill flex table, are you clearing it before populating with data again ?
EDIT:
see link.
If you can use celltable http://gwt.googleusercontent.com/samples/Showcase/Showcase.html#!CwCellTable (because it holds List of elements it display underneath) or use some collection (ArrayList) to hold data that your FlexTable is displaying. Then you can easily modify that collection and redraw your flex table from it.