Attaching property from another key in Firebase - java

I have a database defined as follow
I can retrieve the cafeList as follow:
ApiManager.getInstance().mainDB.child(CafeModel.DATASET_NAME)
.orderByChild("name").startAt(searchText)
.endAt(searchText + "\uf8ff")
.addValueEventListener(new ValueEventListener()
However I am not sure how can I attach the fact that particular cafe is also set as favorite by my user.

Unfortunately, there is no way to achieve this in Firebase using only a single query. So in your case, you should query your database twice, once to get the cafe list and second to check if one of those cafe objects is favorite or not. However, there is a workaround in which you can create a new section in your user object named favoriteCafe in which you can add all user favorite cafes but this implies duplicating data. This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, i recomand you see this video, Denormalization is normal with the Firebase Database. So in this case, if you want to know user favorite cafes, you can use a single query and attach a listener on this new created location.
Also, when you are duplicating data, there is one thing that need to keep in mind. In the same way you are adding data, you need to maintain it. With other words, if you want to update/detele an item, you need to do it in every place that it exists.

Related

Is it possible to temporarily remove an item from RecyclerView that is connected to Firestore DB?

On the online voting system that I am currently working on, I am preparing for the voting feature. I plan to remove an item from the RecyclerView that the user has already voted on but in a way that it does not remove it from the Firestore database itself. Is there a way to do that? If not, is there any workaround to make my concept work? Thank you in advance for the responses.
I plan to remove an item from the RecyclerView that the user has already voted on but in a way that it does not remove it from the database itself.
The simplest solution would be to add a field of type boolean with the default value of false, into each document. You can simply call it "deleted". When you want to perform a delete operation, don't remove the document from the database, rather change its value from false to true.
If you want to have a temporary removal, you might also consider moving a document from a location to another.
If not, is there any workaround to make my concept work?
You can also use Cloud Functions, to trigger a function that contains a particular logic, when a delete operation takes place.

Android Firebase how to handle real time server to local database connection

As for similar questions on this topic and on ChildEventListener, there is no relevant answer, so heres mine.
I have a local SQLite DB which holds all the data, I also have Firebase realtime database which I'm updating with new entries or real time changes across all users. I'm currently doing it with the use of ChildEventListener as follows:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getDatabase().getReference();
DatabaseReference childRef = rootRef.child("my_root");
ChildEventListener eventListener = new ChildEventListener()
{
....
};
childRef.addChildEventListener(eventListener);
As for functionality, With this code I can get realtime changes on childs, get new entries, deleted childs and everything I need but there is one problem. When this specific activity with the listener loads up, the onChildAdded listener gets called enormous amounts of times for every child on this root, as stated on the documentation:
child_added is triggered once for each existing child and then again every time a new child is added to the specified path
So I though to gain focus on the items that I really need and I have done it with:
rootRef.orderByKey().startAt("-WhatTF123456789")...
But then I have lost my CRUD capabilities because it's listening to the new entries and not all of them.
So I came up with a solution. Keep node with all the changes that has been made to the FireBase database and a node with all the users that have read and made the changes to the local DB to know who needs an update, Then use addChildEventListener to this specific node. But that seems redundant.
What is my options to handle this kind of situation?
The onChildAdded listener gets called enormous amounts of times for every child on this root.
As you already mentioned and as the docs states, this is the expected behaviour. Usually, is not recommended to attach a ChildEventListener on a node (root node) that contains huge amount of data. Please be careful about this practice because when downloading large amount of data, you can get erros like: OutOfMemoryError. This is happening because you implicitly download the entire node that you are listening to, along with all the data beneath it. That data might be present as simple properties or, as complex objects. So it can be considered a waste of resource and bandwidth. In this case, the best approach is to flatten the database as much as possible. If you are new to NoSQL databases, this practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you take a look at:
This video, Denormalization is normal with the Firebase Database.
Official docs regarding Best practices for data structure in Firebase realtime database.
My answer from this post: What is denormalization in Firebase Cloud Firestore?
This article, Structuring your Firebase Data correctly for a Complex App.
This article, NoSQL data modeling techniques.
Please also note that when you are duplicating data, there is one thing that need to keep in mind. In the same way you are adding data, you need to maintain it. With other words, if you want to update/detele an item, you need to do it in every place that it exists.
I also recommend you to see the last part of my answer from the following post:
What is the correct way to structure this kind of data in firestore?
It is for Cloud Firestore but same rules apply to Firebase realtime database.
But then I have lost my CRUD capabilities because it's listening to the new entries and not all of them.
Everything in Firebase is about listeners. You cannot get realtime updates for objects within a node, unless you are listening to them. So you cannot limit the results and expect to get updates from objects that you are not listening to. If you need to get updates for all objects within a node, you need to listen to all of them. Because this approach isn't practical at all, you can either use denormalization as explained above or to restrict the results by using queries that can help you limit the amount of data that you get from the database. Regarding your solutions, the second one is much preferred but you can also consider another approach which would be to load data in smaller chunks according to a timestamp property, or according to any other property that you need.
Edit: According to your comment:
Can you please provide tests for each solution (1.denormalization, 2.my solution) examine use of bandwidth and resources and which one is really preferred?
All data is modeled to allow the use-cases that an app requires. Unfortunately, I cannot do tests because it really depends on the use-case of the app and the amount of data that it contains. This means that what works for one app, may be insufficient for another app. So the tests might not be correct for everyone. The denormalization process or your solution is entirely dependent on how you intend to query the database. In the list above, I have added a new resource which is an answer of mine regarding the denormalization tehnique in NoSQL databases. Hope it will also help feature visitors.
I would make a root node with the name, for example, MaintenanceUpdate.
All clients are subscribed to changes here.
As soon as MaintenanceUpdate becomes = true, all clients unsubscribe from changes to the main "database". And then (when MaintenanceUpdate = false) are re-subscribed again.
At this time you are updating the database.
I have similar requirements, with Firebase and Room, while I've solved it alike this:
public class BaseModel extends BaseObservable implements IDataModel {
/** Sqlite default PK */
private int itemId = 0;
/** Firebase uniqueId */
#ColumnInfo(name = SqliteBaseHelper.KEY_FIREBASE_UNIQUE_ID)
protected String uniqueId = null;
/** Firebase lastSync */
#ColumnInfo(name = SqliteBaseHelper.KEY_FIREBASE_LAST_SYNC)
protected long lastSync = 0;
...
}
this means, when a local record has a KEY_FIREBASE_UNIQUE_ID which is null and the KEY_FIREBASE_LAST_SYNC is 0, it has to be inserted into Firebase - else it would check, when running a synchronization AsyncTask, if the local or remote record needs to be updated. this is because the main issue is, that when inserting remotely, the ChildEventListener will attempt to synchronize duplicates to the same client - unless having such indicators for the synchronization status in place, locally and remotely. the local primary keys might vary across the clients (depending for how long they were offline and how many records where locally inserted during the offline state), while the synthetic KEY_FIREBASE_UNIQUE_ID is used for identifying them; it's the "key to success".

Necessity of storing variables in Firebase Database

So I am wondering about how necessary it is to store variables in the realtime firebase database if I want all Users at access the same dynamic variable.
So for instance, I have a arraylist that stores the list of open games, and if I want this list to update in realtime for every user should this List in firebase realtime database?
Sorry for the simplicity of the question
Yes, it may be a simple question, but it surely pops in head of everyone, once.
I think for updating any list dynamically in real time, would require you to access any kind of database.
It is not necessary to have it on Firebase database, but any database online, that can tell every open instance of your app that the list has to be updated at a particular instant.
The main reason of why you need it to be on database is updating it in real time and that too dynamically.
If it's not dynamic, meaning the content that you need, can be hardcoded then one way would be placing everything you need in your code and using timer or something like that to fire at particular moments to update things in your app.
Also that aside, sorting, storing and changing data is much simpler using a database, which also becomes one more reason for you to use a database like Firebase to keep content of your app that has to be updated frequently in real time.
You can know more about database in this Google link, I found.

How to save form data into database in android sdk

I need help with adding a database in my app for android. What I want to do is save name, address, if certain checkboxes are checked and textbox data. so far this is what I have in my main activity xml and java (download links):
https://www.dropbox.com/s/vp4fg0f5kx0p5it/activity_main.xml?dl=1
https://www.dropbox.com/s/p2dkqtoe8h1dl85/MainActivity.java?dl=1
All the other questions and tutorials just don't seem able to be grasped by my mind. I want to save the "name", "address", "AirSealing", "airsealnotes", "DuctSealing", "BlowerDoor", "ductsealnotes", "blowdoornotes", "Light", "lightnotes", "othernotes", "HPD", "HPGJGNY", "Placeholder", and the save button to save data.
There's a lot of boilerplate code associated with creating and handling an SQLite database (even just one with a single table), so don't feel bad about not getting it right away.
Here's the tutorial I personally used to grasp SQLite databases in Android:
http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
Essentially, you'll want to follow the tutorial, only replacing their columns (a name and phone number) with the data you want to store. The custom helper class isn't mandatory - you can simply take the code they put in the DB handler class and write it in your main activity class instead - but it makes writing and retrieving data a lot easier.
Also, a word of warning: you won't be able to store every type of data in a database out of the box. For instance, if you want to store a boolean (which would be your checkboxes), you'll have to do it by storing, say, an integer or a string, instead of an actual boolean.

Best option to update Facebook contact list in Android app

I'm working on an application that retrieves the list of Facebook contacts to later perform different actions with it (for example, open a chat).
I have retrieved the list, but I have doubts about which is the best strategy to preserve and applying it to the changes that occur (eg chat be available for a new contact).
What is the best approach? As a first option I created a java class and serialized entire contact list (with their profile picture). After I have saved on the SD card and leave it available for later retrieval when needed. But I'm thinking maybe it is better to create a service in Android that instantiates a class that store a HashMap of contacts and leave it in memory for watching it constantly updating.
What do you think about this?
thanks

Categories