Firebase Fire store database replacing all data to single one - java

I have an error. when the user uploads his image. the other data were gone and only the profile URI is visible.
Currently, I have 5 strings
name
email
password
profile(image URI)
refer id
coins
However, when a user uploads their profile photo, all the data is removed.
showing only the profile image URI
I have attached the code here
private void updateUserProfile() {
Map<String,String > profile = new HashMap<>();
profile.put("profile",imageUri.toString());
database
.collection("Users") // the path of users.
.document(FirebaseAuth.getInstance().getUid()) // to update in the current users.
// .update(user)
.set(profile)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
Toast.makeText(getContext(), "Photo Updated!", Toast.LENGTH_SHORT).show();
}
});
}

If you just looking to update a single field when can do so without using any Map values.
firestore.collection("YOUR_COLLECTION").document(user.getUid()).update("profile", imageUri.toString())
.addOnCompleteListener(task -> {
});

If you call .set(profile), you're replacing the existing data with whatever is in profile. If you want to merge the values in profile with any existing data in the document, use .update(profile) instead.
Also see the Firebase documentation on updating data in a document.

thanks for your answers. I already solved the problem. I have attached the codes below.
private void updateUserProfile() {
Map<String, Object> profile = new HashMap<>();
profile.put("profile", imageUri.toString());
final DocumentReference sDoc = database.collection("Users").document(FirebaseAuth.getInstance().getUid());
database.runTransaction(new Transaction.Function<Void>() {
#Override
public Void apply(#NonNull Transaction transaction) throws FirebaseFirestoreException {
DocumentSnapshot snapshot = transaction.get(sDoc);
transaction.update(sDoc, profile);
// transaction.update(sDoc, "name", binding.nameBox.getText() );
return null;
}

Related

Why my Firebase firestore data is not showing in android

I am working on an application where anyone can list their products. I am storing data in Firebase Firestore in nested collection Now I want to retrieve that data and show that on my home screen. Now the data is showing but the problem is that it is showing only when I am login in with that same number through that I list that data into Firebase but when I try to log in with another number the data doesn't show. I want that to show to everyone who logged in to the app. Basically My app is just like OLX where anyone can list anything which shows to everyone.
MY CODE TO RETRIEVE THE DATA
//CODE TO GET CURRENT ID OR USER
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
//CODE TO GET THE DATA FROM FIREBASE
DocumentReference uidRef = firebaseFirestore.collection("listing_details").document(uid);
CollectionReference roomDetailsRef = uidRef.collection("room_details");
String doc_id = roomDetailsRef.document().getId();
roomDetailsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document != null) {
RoomsDetails obj = document.toObject(RoomsDetails.class);
roomsDetails.add(obj);
}
}
roomsAdapter.notifyDataSetChanged();
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
You have .document(uid) in your path where UID is User ID of user currently logged in. When you use another phone number, that's a different user.
If you want to fetch room_details documents from all listing_details documents then you can use Collection Group queries like this:
db.collectionGroup("room_details").get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
// ... iterate over all docs and render
}
});

Firebase Firestore storing data in Realtime Frestore for same collection ID

I have a form which insert record with multiple values for userID logged in .
Whenever I am submitting a second time form, it's updating existing record rather than inserting new record .
I need to be able to insert multiple records for same documentID(collectionID) rather than updating existing record
String uniqueID = UUID.randomUUID().toString();
DocumentReference documentReference = fStore.collection("data").document(userID);
Map<String, Object> user = new HashMap<>();
user.put("date", dates);
user.put("vehicle_number", vehicle_number);
user.put("cost", costs);
user.put("liters", liters);
user.put("fuel_type", sp);
user.put("ID", uniqueID);
documentReference.set(user).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(adding_vehicle_expense.this, "Data inserted", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("here2" + TAG, "onFailure: " + e.toString());
}
});
Firebase
There is no way to have multiple documents directly inside another document. But it is possible to have a subcollection under a document, and then add multiple documents in that subcollection by calling add().
E.g.
documentReference.collection("userdata").add(user).addOnSuccessListener(new OnSuccessListener<Void>() {
...

How to sort a map of Firebase DocumentReferences by date?

I'm trying to build a small chat app using Firebase cloud. I have created the following structure in Firebase database:
Collection "users" -> bob#gmail.com document -> map of "chat rooms" field (type Map<String, DocumentReference>)
Collection chatRooms -> room id document -> Collection messages -> message id document -> fields
The message id document contains the following fields:
from: the user that sent the message
message: the text of the mesasage
sentAt: Date
I want to create a RecyclerView of all the chat rooms of the current user. So what I did is:
FireDB.collection("users").document(connectedEmail).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Log.d(this.getClass().getName(), "addOnSuccessListener:success");
if (!(documentSnapshot.exists())) {
// TODO
return;
}
Map<String, DocumentReference> chatRooms = (Map<String, DocumentReference>) documentSnapshot.get("chatRooms");
if (chatRooms.isEmpty()) {
// TODO
return;
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(this.getClass().getName(), "addOnSuccessListener:failed");
}
});
What would be the easiest way to the chatroom map by the date of the last message? I thought of keeping in the room id document level the latest time this document was touched but I want to know if it's possible to do using Firebase without adding special support.
Yes, You have to update chat room Document whenever a message is sent,
Firebase Firestore doesn't automatically add a timestamp to the write.
Let's say you have field "updated_at" (time in Timestamp) inside the room document,
whenever a message is sent in this room, you just have to update it with the latest timestamp.
Then you can get all the rooms in a particular order.
Why saving time in Timestamp?
Firebase Recommends it.
It easier to query the documents using the DIRECTION in orderBy
Can be converted easily to any date display without much code
Implementation example
FirebaseFirestore.getInstance().collection("YOUR_COLLECTION")
.whereEqualTo("your_key", "your_value")
.orderBy("lastUpdateTime", Query.Direction.DESCENDING)
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (queryDocumentSnapshots != null) {
if (!queryDocumentSnapshots.isEmpty()) {
//DATA returned, You can use Gson to convert them to your POJO list
} else {
//NO DATA RETURNED
}
}
}
});

How Should I fetch the document fields and use them in another map for another collection?

How should I fetch the document fields from one collection and combine them to add a new document to another collection? I have attached picture of the database how does it looks, I want to fetch the fields from the collection show and want to update it to the new collection along with some other data:
private void savePost(String mPostTitle, String mPostContent, String mlistSpinnerC) {
final DocumentReference docRef = FirebaseFirestore.getInstance().collection("users").document(mauth.getCurrentUser().getUid());
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
String username = (String)
document.get("username");
String email= (String) document.get(email);
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
postMap.put(Constants.POSTTTITLE, mPostTitle);
postMap.put(Constants.POSTCATEGORY, mlistSpinnerC);
postMap.put(Constants.POSTCONTENT, mPostContent);
postMap.put(Constants.TIMESTAMP, (System.currentTimeMillis()/1000));
postMap.put(Constants.USER_ID,mauth.getCurrentUser().getUid());
postMap.put("username", username);
PostsRef.document().set(postMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Intent toHomeActivity = new Intent(AddPostActivity.this, MainActivity.class);
startActivity(toHomeActivity);
}
}
});
I am just not able to map the fields from one collection to another collection, please guide me the correct method to that.
By the time you are trying to add the username to your postMap using the following line of code:
postMap.put("username", username);
The data has not finished loading yet from the database and this is because the listener you have added to your get() call is being invoked some unknown amount of time later after your query finishes. You don't know how long it's going to take, it may take from a few hundred milliseconds to a few seconds before that data is available. The onComplete() method has an asynchronous behavior, that's why you cannot get that username in such a way.
A quick solve for this problem would be to move all that block of code related to adding data to the postMap, inside the onComplete() method. In this you are waiting for the callback and username your will be available. Otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Cloud Firestore - Get Documents From Multiple Locations

When the user checks his friends list in my app, I want the app to go through each user in the list and retrieve his up to date information from the Cloud Firestore.
This is my current code:
final CollectionReference usersRef= FirebaseFirestore.getInstance().collection("users");
usersRef.document(loggedEmail).collection("friends_list").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
if (!documentSnapshots.isEmpty()){
for (DocumentSnapshot friendDocument: documentSnapshots) {
usersRef.document(friendDocument.getString("email")).get().addOnSuccessListener
(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
User friend=documentSnapshot.toObject(User.class);
friendsList_UserList.add(friend);
}
});
}
///...
}
else
noFriendsFound();
}
And this is an illustration of my wanted process:
As you can see, I can get the information of each user in this way, but I can't find a way to listen to this process, and proceed when I have the information about all the friends in the user's list.
Is the a way which I'll be able to get all of the friends information at once?
Firestore does not directly support joins like you're asking for.
You could construct a chained listener using the getDocumentChanges in the QuerySnapshot to keep track of which friends you should listen to.
Imagine if you kept a map of friend listener registrations like this
Map<String, ListenerRegistration> friendListeners = new HashMap<>();
Then you could register something like this:
usersRef.document(loggedEmail).collection("friends_list")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(QuerySnapshot snapshot, FirebaseFirestoreException error) {
for (DocumentChange change : snapshot.getDocumentChanges()) {
DocumentSnapshot friend = change.getDocument();
String friendId = friend.getId();
ListenerRegistration registration;
switch (change.getType()) {
case ADDED:
case MODIFIED:
if (!friendListeners.containsKey(friendId)) {
registration = usersRef.document(friendId).addSnapshotListener(null);
friendListeners.put(friendId, registration);
}
break;
case REMOVED:
registration = friendListeners.get(friendId);
if (registration != null) {
registration.remove();
friendListeners.remove(friendId);
}
break;
}
}
}
});
Note, however that this may not actually be a good idea. You may be better off pushing enough information down into the friends_list documents that you only need to load the actual friend user document once you're actually drilling down into that friend's details.

Categories

Resources