Firebase Document reference where value may change - firebase

I have a situation where I have a collection which contains information that displays a user profile picture, this user picture is taken from another collection's (users) document. My problem is that I add a link to the picture when I create the new document, this means that if in future the user changes the profile picture the other collection would not have that new information. Is there a way I can solve this with firebase?
I want to get the data from the other collection whenever the information in users collection is updated.
document value in the collection that needs live data
{profile-picture:"image-from-users-collection goes here"}
document value in /users collection
{user-picture:"my-pic.png"}

I want to get the data from the other collection whenever the
information in users collection is updated.
A mentioned by Mises, one standard approach is to use a Firestore Cloud Function which is triggered when the user document changes.
The following code will do the trick. I make the assumption that the document of the other collection uses the same ID than the user document.
exports.updateUserImage = functions
.firestore
.document('users/{userId}')
.onUpdate(async (change, context) => {
try {
const newValue = change.after.data();
const previousValue = change.before.data();
if (newValue['user-picture'] !== previousValue['user-picture']) {
await admin.firestore().collection('otherCollection').doc(context.params.userId).update({'profile-picture':newValue['user-picture']});
}
return null;
} catch (error) {
console.log(error);
return null;
}
});

Related

Flutter-Firestore: - Code to retrieve data from firestore then save/use it

I am very new to Dart, and coding in general. I have produced this code after watching tutorials on YouTube. For the most part, I have been able to troubleshoot most of my problems on my own, here I feel I need some help. I wanted to extract all the fields from a document and use it. I have tried a few codes but there is no proper solution anywhere online.
Here is the code I used to retrieve it:-
documentID = '9zjwixClgwR1Act1OlPK'
firebaseGetData(documentID){
firebaseFirestore.collection('course').doc(documentID).get().then((value) {
print(value.data());
});
}
Here is my database file structure:-
I want to store all the fields in variables and use them. please help me with the correct code, please.
There are two ways to retrieve data stored in Cloud Firestore. Either of these methods can be used with documents, collections of documents, or the results of queries:
Call a method to get the data
const docRef=doc(db,’course’,'9zjwixClgwR1Act1OlPK')
getDoc(docRef)
.then((doc) => {
console.log(doc.data(),doc.id)
})
Set a listener to receive data-change events.
To get real-time data when you set a listener, Cloud Firestore sends your listener an initial snapshot of the data, and then another snapshot each time the document changes.
const docRef=doc(db,’course’,'9zjwixClgwR1Act1OlPK')
onSnapshot(docRef,(doc) => {
console.log(doc.data(),doc.id)
})
For more information, kindly check link1 & link2
Firstly you need to create firestore instance. Your function must be async and return a Future value. Also, you can check this document.
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<Map<String, dynamic>> firebaseGetData({required String documentID}) async {
DocumentSnapshot ds =
await _firestore.collection("course").doc(documentID).get();
Map<String, dynamic> data = ds.data() as Map<String, dynamic>;
print(data["videoDescription"] as String); // check if it null or not
return data;
}
// creating a instance variable
final CollectionReference firestoreInstance =
FirebaseFirestore.instance.collection('course');
void _loadUserData() async {
await firestoreInstance.doc(documentID).get().then((event) {
// you can access the values by
print(event['isDOne']);
print(event['lastViewedOn']);
print(event['lectureNo']);
print(event['videoDescription']);
print(event['videoUrl']);
});
}
call the _loadUserData() function whenever you need to fetch the data.

Firebase Document Fields are getting Deleted

For some time now, I have noticed that the fields of some of my firebase documents get deleted, even though I do not delete them or write any logic on my app to delete fields of a document or a document itself. This is a picture that shows a document on my firebase project, which has its fields deleted on its own.
The firebase project is connected to my flutter app, but I have not written any delete functionality.
I only update the fields occasionally with recent data.
Please, who has any idea of what's happening?
Edit
This is how I update the documents of my user collections
Future<String?> submitUpdate(User user) async{
CollectionReference userCollection = firestore.collection('users');
String? uid = await secureStorage.read(key: 'uid');
try{
//updates user doc in users collection
await userCollection.doc(uid).update(user.toMap());
return "Success";
}catch(e){
return null;
}
This is how i create the user document in the users collection.
Future<String?> saveUserCredentials(User user) async{
CollectionReference users = firestore.collection('users');
String? uid = await FlutterSecureStorage().read(key: "uid");
try{
//creates a user doc in the users collection
await users.doc(uid).set(
user.toMap()
);
return "Success";
}catch (e){
print(e);
return null;
}
I have a User model that defines the user object.
If you want to set some fields of a document, but keep existing fields, use set with SetOptions(merge: true):
FirebaseFirestore.instance
.collection(...)
.doc(...)
.set({'field1': value1, 'field2': value2}, SetOptions(merge: true));
Without this, the existing fields that are not listed in set will be not be kept, probably this happened to you.

Firestore nodes deleted on transaction

When I add to a document using below code I will successfully be able to keep adding additional objects to the array, as long as I stay on the same screen.
void createRecord(dataMap) async {
_user = await FirebaseAuth.instance.currentUser();
var createTransaction = (Transaction tx) async {
var ds = await tx.get(db
.collection('users')
.document(_user.uid)
.collection("days")
.document(DateFormat("yyyy-MM-dd").format(dataMap['day'])));
await tx.set(ds.reference, dataMap);
};
Firestore.instance.runTransaction(createTransaction);
}
After navigating off the screen then back all objects are deleted when trying to add new ones.
When I navigate back from a screen how can I add new objects to the collection with out deleting the old ones?
Thanks.
To add a new, unique item to an array, you can use the arrayUnion operator.
Something like:
await tx.update(ds.reference, {
'breakfast': FieldValue.arrayUnion(dataMap['breakfast'][0])
});
Also see:
how to add or remove item to the the existing array in firestore ?
flutter firestore, add new object in array
How do update array values in Flutter cloud_firestore?

How to delete a subcollection from firestore flutter

so am new using firestore to store data. at the moment i need to delete data already saved in the Firestore through my App. I have tried
Future<void> removeDocument(String id, String userId){
return ref.document(userId).collection(userId).document(id).delete().whenComplete((){
print("DELETE DONE::");
});
}
But its not working.
The thing is I used the userId to save the user details
now I want to delete the data but it does not delete the data even though the print message shows in my Log.
The method below is how i add data to the Firestore
Future<void> addDocument(Map data, String userId){
return ref.document(userId).collection(userId).add(data);
}
void setupLocatorWorkout() {
locatorWorkout.registerLazySingleton(() => Api('workout_goal'));
locatorWorkout.registerLazySingleton(() => CRUDRemoteDataSource());
}
Api(this.path){
print("$path");
ref = _db.collection(path); // this is the base collection
}
please what am i doing wrong here?
Thank you!!!
Delete a User by UID:
void deleteUser(User user) async {
await db.collection(COLLECTION_NAME)
.document(user.uid)
.delete()
.then((_) {
print('User deleted.');
});
}
Don't forget to add import 'dart:async'; at the top
The answer is you shouldn't.
According to the Firestore docs, you should not do this because:
While it is possible to delete a collection from a mobile/web client, doing so has negative security and performance implications.
However the link shows how it can be done frome some platforms.

How to create a custom document in collection - Firestore with Flutter

I sign in my user through google, after successfully login. I wants to create document for each user inside user_details collection and the document name should be google id. But its auto generating document name.
Is there any way to create custom document in Firestore?
Thanks in Advance
// Store data in Firestore
storeData(User user) async {
DocumentReference documentRef =
Firestore.instance.collection("user_details").document(user.id);
Firestore.instance.runTransaction((transaction) async {
await transaction.set(documentRef, user.toJson());
print("instance created");
_login.add(Result(Status.SUCCESS, "Login successful.", user));
});
}
Try this await documentRef.setData(user.toJson());

Resources