How can I change multiple documents - java

How can I change multiple documents? I have 2 collections firestore. One (users) is for user account (email, name, etc).
To second collections (dashboard) users can add some message to a board. In this second collection is name, category, time etc.
What I want to do is when someone change his name or faculty in account, it will also change in second collection for each his comment so it will show up to date information
DocumentReference documentReference = fStore.collection("users").document(user.getUid());
Map<String, Object> edited = new HashMap<>();
edited.put("email",email);
edited.put("smallName",StringUtils.unaccent(profileName.getText().toString()).toLowerCase());
edited.put("fullName",profileName.getText().toString());
edited.put("fakulta",mySpinner.getSelectedItem().toString());
documentReference.update(edited).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(EditProfile.this, "Profile data are changed", Toast.LENGTH_SHORT).show();
//startActivity(new Intent(getApplicationContext(),MainActivity.class));
finish();
}
Firestore
Is there any way to do it without changing the whole structure of my app?

To update the user names in the comment docs, you'll need to:
Query the collection to find the comments by the user who updated their name. If you stored the UID for each user in the comment document, this would look something like fStore.collection("dashboard").where("uid", "==", "theUidOfTheUserWhoUpdatedTheirName"). If you didn't store their UID, you'll have to query on the old value of their name instead, but the code will be similar.
Loop over the query results and update each document in turn. If you have a lot of these, you may want to read about the fastest way to do this here: What is the fastest way to write a lot of documents to Firestore?

Related

Save button deletes previous data in firebase

I am new to android studio and firebase. I am trying to save a list of people to firebase like this. Idea is that the logged in user should be able to save information about some people.
String userId = user.getCurrentUser().getUid();
databaseReference.child("users").child(userId).child("savedPersons").child("name").setValue(nameTxt);
databaseReference.child("users").child(userId).child("savedPersons").child("surname").setValue(surnameTxt);
databaseReference.child("users").child(userId).child("savedPersons").child("gender").setValue(genderTxt);
databaseReference.child("users").child(userId).child("savedPersons").child("ageTxt").setValue(ageTxt);
It does not surprise me that it deletes the previous saved person when i save another one but i don't know how to save all of them. I have this in my firebase but i need multiple saved users. How do i do it ?
Firebase screenshot
If you want to save multiple people in a list in the database, you'll want to call push:
String userId = user.getCurrentUser().getUid();
DatabaseReference newRef = databaseReference.child("users").child(userId).child("savedPersons").push(); // 👈
newRef.child("name").setValue(nameTxt);
newRef.child("surname").setValue(surnameTxt);
newRef.child("gender").setValue(genderTxt);
newRef.child("ageTxt").setValue(ageTxt);
This will create a new child node under savedPersons each time you call push(). To learn more on this, see the Firebase documentation on appending data to a list.
Note that calling setValue for each property is wasteful, and may lead to unexpected behavior down the line. I recommend putting all values in a map, and then adding them all with one call to setValue:
Map<String, Object> values = new Map<>();
values.put("name", nameTxt);
values.put("surname", surnameTxt);
values.put("gender", genderTxt);
values.put("ageTxt", ageTxt);
newRef.setValue(values);

How do I query a user's info in Firestore if all my document IDs are auto-generated?

All of the examples I'm finding online have very simple document IDs, but what do you do if you're auto-generating all your IDs (as the docs say you should)? For example, I want to query the date when the user was created. The document ID for this is below, but I've just copy-pasted it from the Firestore console. How would I know the document ID so that I may query any user's info? Note that I will be have a users, groups, usergroups, etc... There will be quite a few collections, each using the auto-ID feature. I would need to be able to update any row in any collection.
val docRef = db.collection("users").document("9AjpkmJdAdFScZaeo8FV45DT54E")
docRef.get()
.addOnSuccessListener { document ->
if (document != null) {
Log.e("Query", "Data: ${document.data}")
} else {
Log.e("Query", "Document is null")
}
}
.addOnFailureListener { exception ->
Log.e("Query", "Failure")
}
If you have data to query, that should all be stored as fields in the documents. Don't put that data in the ID of the documents - use field values.
You can filter documents in a collection using "where" clauses as shown in the documentation. What you're showing here isn't enough to go with in to make specific recommendations. But you definitely want to think about your queries ahead of time, and model your data to suit those queries.
If you need to update a document, you must first query for it, then update what you find from the query. This is extremely common, as Firestore does no provide any SQL-like "update where" queries that both locate and update data in the same command.

How to delete from Firebase Realtime Database using key?

I'm currently working on a project and I need to be able to delete from a database I've already created. I created it using the .push() to the database hence a unique key is created and thus needed for delete operations.
I tried using the answer from Frank Van Puffelen here How to delete from firebase realtime database?, but I ran into a bug where if two nodes have the same title they'll be deleted.enter image description here
The image shows how my Firebase database looks:
A bit of assistance or direction to an answer would go a long way. Thanks
If you want to delete a single element from your database, you need to know the path to that element, which includes also that pushed key. Your reference should look like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference keyRef = rootRef.child("-KlSNx87aYigsH3lLp0D");
keyRef.removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d("TAG", "Element removed successfully!");
}
}
});
Otherwise, you can use a query that looks exactly like this:
Query idQuery = rootRef.orderByChild("id").equalTo(1);
In this case, Frank Van Puffelen's answer from the following post:
How to delete from firebase realtime database?
Will work perfectly fine.

Reading From Cloud Firestore - Items Briefly Null

I am reading data from Firebase Cloud Firestore and populating them into my UI. Below is my data structure:
Below is my code to read the data from the Cloud Firestore and populate the UI. I am noticing that for my TextView, the item is briefly null before it displays the "Test Q 2." Am I reading data incorrectly? After a split second, the TextView populates the question from Firebase, but I find it odd that it is briefly null and the null is visible in the UI:
mStoreBaseRef = FirebaseFirestore.getInstance();
mStoreSelectedPollRef = mStoreBaseRef.collection(POLL_LABEL).document(pollID);
mStoreSelectedPollRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Poll selectedPoll = documentSnapshot.toObject(Poll.class);
String pollQuestion = selectedPoll.getQuestion();
mPollQuestion.setText(pollQuestion);
mPollQuestion.setTypeface(null, Typeface.BOLD);
}
});
Data is loaded from Firestore asynchronously. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before that data is available.
So the brief time before the poll is populated is the expected behavior. If this is confusing for your users, you might want to populate it with good default values, or show a "loading, please wait" type message.

Organizing firebase data

I am using Firebase Auth and Firebase Database to store student's profiles and students reports.
When the user signs up they input email, password, school name, school year, school discipline. I use the email and password for the Auth but the rest of the info is stored in the Database with a unique ID as shown below:
For the reports, each students can input many entries, each with its unique ID as shown below:
Here are my questions:
Once a student logs in, how can I find their profile info since the parent is a unique ID. In other words is there a way to search through the database for that students email (for example, mido4#hotmail.com, in the image) and from that get the students name (in this case, Emina Osman)?
Once you get the student's name, how can you search for all the entries that student has saved in the database? For each entry the student has, the student name is saved.
Not sure if the way I setup the database is ideal so is there a better way?
Thanks for your time! Any help would be really appreciated!
Yes, it is. The simplest way to achieve this, is to change your database structure a little bit. So instead of using as a unique identifier, the pushed key, generated by the push() method, i suggets you using the email address. It's also unique and easy to use. The benefit is, that is allows you to search your database for that particular email. Your database structure should look like this:
flashscreen-1d252
|
--- Users
|
--- mido4#hotmail,com
| |
| --- //User Details
|
--- mido5#hotmail,com
|
--- //User Details
Note, that Firebase does not allow symbols as . (dot) to be used in a key. So as you probably see, i have changed the . dot with a , (comma). I have achieved this using the below method:
String encodeUserEmail(String userEmail) {
return userEmail.replace(".", ",");
}
To search for an user and get the name, simply add a listener on Users node like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userRef = rootRef.child("Users").child("mido4#hotmail,com");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
String firstName = dataSnapshot.child("firstname").getValue(String.class);
String lastName = dataSnapshot.child("lastname").getValue(String.class);
Log.d("TAG", firstName + " " + lastName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);
The output will be: Emina Osman
You'll have to search after the email address and not after the name.
Already answered above. This database structure is more efficient.
Edit: There 2 additional questions regarding this answer based on using the email address vs. uid.
What if a user decides to delete his account and after a while decides to return and tries to sign-in again? If we are using the email address, nothing happens. If we are using the uid, when the user signs in for the second time, another uid is generated, which is obvious that is different from the first one and this the moment in which you are in trouble, because even he is the same user, he is treated as a new one.
What if the users email address changes? IMHO, an email can be changed only if you decide to change it. Personally, I haven't changed my email address in years but I have deleted hundreds of accounts from hundreds of applications. Even if you change your email address, there's no much of a problem. You login in your application, change the email address and that's it. You'll have also all your history within that application. Having a unique identifier a uid, in case you delete the account and you come back again, you start from zero.
Once a student logs in, how can I find their profile info since the
parent is a unique ID.
Super easy! When a users account is created initially, Firebase assigns the user a 'random' and unchanging user uid (uid). That uid is what identified that specific user to Firebase. That's what you should store there info under within the users node like this:
users
uid_0
name: "users name"
Then when they authenticate in the future, firebase provides that uid to you in the authentication process. You can then simply get their user information from the users node via that uid. i.e. read the node /users/uid_0
Once you get the student's name, how can you search for all the
entries that student has saved in the database?
Again, super simple. For every entry you make in Firebase, reference that uid. For example, say you want to keep track of each users reports
reports
uid_0
-9i9sdjj3i0a09djads //create with push() or childByAutoId() in swift
reportName: "some report"
-ua9sd9i9i3i0idsfi
reportName: "another report"
Then to get all of their reports, read the node /reports/uid_0
conversely, you can store the reports and then a link to the user
reports
-9i9sdjj3i0a09djads
reportName: "some report"
report_by: "uid_0"
and with that structure a query can be done where report_by is equal to "uid_0" to return all of uid_0's reports.
Not sure if the way I setup the database is ideal so is there a better
way?
there's a number of different ways to achieve what you want but the above is a very common design pattern.

Categories

Resources