I have the function that I am using to create or update customer.
I am able to successfully write to db. I created a field called user_id where I save the currentUser uid into so I can read only logged in user documents.
However, I am unable to update the documents because I know I'm probably not referencing the document the right way.
I get the following error:
flutter: Error: PlatformException(Error 5, FIRFirestoreErrorDomain, No
document to update:
What am I doing wrong?
Here's my function below:
Future createOrUpdateCustomer(Customer customer, bool isUpdating) async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
String userId = user.uid;
print('Current logged in user uid is: $userId');
CollectionReference customerRef =
await Firestore.instance.collection('customers');
if (isUpdating) {
customer.updatedAt = Timestamp.now();
customer.userId = userId;
await customerRef.document().updateData(customer.toMap());
print('updated customer with id: ${customer.id}');
print('updated customer with logged in uid: ${customer.userId}');
} else {
customer.createdAt = Timestamp.now();
DocumentReference documentReference = customerRef.document();
customer.id = documentReference.documentID;
customer.userId = userId;
print('created customer successfully with id: ${customer.id}');
await documentReference.setData(customer.toMap(), merge: true);
addCustomer(customer);
}
notifyListeners();
}
You are trying to update a nonexistent document. In this line,
await customerRef.document().updateData(customer.toMap())
You are creating a document reference with a randomly-generated id. You should explicitly set the id of the document you're updating.
I think you can update the document with conditions but the reference must be the doc id, that you see in 2nd section of firestore interface.
Related
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
Future<void> userSetup(String displayName) async{
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser.uid.toString();
CollectionReference users = FirebaseFirestore.instance.collection("Users");
users.add({
'displayName': displayName,
'uid': uid,
// 'docID': docID,
});
return;
}
Just to preface, I'm a complete beginner with Flutter.
This is what I'm using to add the collection in Firestore but I'd like to retrieve the the specific document ID and use it for further storage. Is there a method to obtain and store the document ID in the user details? I'm trying to retrieve the specific user's name when they login and display it on the homepage.
You may try this method
Preset the document id with your own, you may use the package uuid
https://pub.dev/packages/uuid
or use the user's uid as the doc id
//final docID = Uuid().v4(); //use custom uuid for doc id
//final docID = uid; //use user id as doc id
users.doc(docID).set({
'displayName': displayName,
'uid': uid,
});
Then save the docID to user device with shared_preferences for persistant storage
https://pub.dev/packages/shared_preferences
If you want to store the ID inside the document, you can first create the DocumentReference for the new document by calling CollectionReference.doc() without parameters:
CollectionReference users = FirebaseFirestore.instance.collection("Users");
var newDocRef = users.doc();
var newDocId = newDocRef.id
users.add({
'displayName': displayName,
'uid': uid,
'docID': newDocId
});
You can retrieve **firestore** doc id only when you retrieve the data using a stream builder. Take a look at the code.
Streambuilder(
stream: Firestore.instance.collection("Your collection").snapshot(),
builder: (context,snapshot) {
if(snapshot.hasData) {
List<User> users = []
for(var doc in sanpshot.data.documents) {
users.add(
new User(
name: doc.data["name"],
email: doc.data["email"]
**id: doc.documentID**
)
)
return Column(
children: users
)
}
}
}
)
In the case that you do not want to use custom IDs for your documents but instead rely on firebase auto generated IDs you can do the following.
Future<void> userSetup(String displayName) async {
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser.uid.toString();
CollectionReference users = FirebaseFirestore.instance.collection("Users");
users.doc(uid).set({
'displayName': displayName,
});
return;
}
This will set the document ID to be the same as the users uid. The benefit of this approach is two fold.
You do not have to set an additional id property in the document.
You can now query the users collection for the specific user using the currently signed in users uid
At runtime, components are able to read the contents of their own package by accessing the path /pkg/ in their namespace. The resource() template may be used to add contents to the package that may be accessed this way.
The 'utenti' (users) collection contains a document for each user which in turn contains the 'salvataggi' (saves) collection to save objects within the app.
Each document inside 'salvataggi' (saves) has an automatically generated id containing a series of data (String to be precise).
Documents within 'salvataggi' (saves) can be added by saving objects created from two other collections always in FIrestore.
When, through a button, I want to delete an object from the 'salvataggi' (saves) collection, a random document is deleted and not the one corresponding to the object.
Screenshot of Firestore
Object 1
final CollectionReference _usersRef =
FirebaseFirestore.instance.collection('utenti');
final User _user = FirebaseAuth.instance.currentUser;
//Add
Future _addToSaved() {
return _usersRef.doc(_user.uid).collection('salvataggi').doc().set({
'fonte': elenco.fonte,
'title': elenco.title,
'url': elenco.urlAvv,
'imageEv': elenco.urlAvv,
'p1': elenco.iconaProspettiva1,
'p1url': elenco.urlProspettiva1,
});
}
//Remove
Future _removeFromSaved() async {
CollectionReference userSaved =
_usersRef.doc(_user.uid).collection('salvataggi');
QuerySnapshot querySnap = await userSaved.get();
querySnap.docs[0].reference.delete();
}
Object 2
final CollectionReference _usersRef =
FirebaseFirestore.instance.collection('utenti');
final User _user = FirebaseAuth.instance.currentUser;
//Add
Future _addToSaved() {
return _usersRef.doc(_user.uid).collection('salvataggi').doc().set({
'fonte': widget.single.fonte,
'title': widget.single.title,
'url': widget.single.urlAvv,
'imageEv': widget.single.imageEvAvv,
'lastupdate': widget.single.dataAggiornamento,
'p1': widget.single.iconaProspettiva1,
'p1url': widget.single.urlProspettiva1,
});
}
//Remove
Future _removeFromSaved() async {
CollectionReference userSaved =
_usersRef.doc(_user.uid).collection('salvataggi');
QuerySnapshot querySnap = await userSaved.get();
querySnap.docs[0].reference.delete();
}
What am I doing wrong? Why does this happen?
When the user saves a document try saving the id of that document with it so whenever the user unsaved the document. You can pass the id of that unsaved document to firestore.
It will look something like this
Future _removeFromSaved(String docID) async {
CollectionReference userSaved =
_usersRef.doc(_user.uid).collection('salvataggi');
await userSaved.doc(docID).delete()
}
--UPDATE--
You can save document id by calling the then method after adding the document to firestore and then updating it
Future _addToSaved()async {
await _usersRef.doc(_user.uid).collection('salvataggi').add({
'fonte': widget.single.fonte,
'title': widget.single.title,
'url': widget.single.urlAvv,
'imageEv': widget.single.imageEvAvv,
'lastupdate': widget.single.dataAggiornamento,
'p1': widget.single.iconaProspettiva1,
'p1url': widget.single.urlProspettiva1,
}).then(docRef=>await _usersRef.doc(_user.uid).collection('salvataggi').doc(docRef.id).update({'id':docRef.id}));
}
querySnap.documents.first.reference.delete();
Use this instead of querySnap.docs[0].reference.delete();
I've been having a problem trying to update data from a logged in user. I have the uid, but there has to be a connection between the uid and the collection of users, so that the program picks the right user to update, but I don't know how to make it.
Here's what I have:
FirebaseUser loggedInUser;
final _firestore = Firestore.instance;
//
double _latitude;
double _longitude;
void getCurrentLocation() async {
try {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
setState(() {
_latitude = position.latitude;
_longitude = position.longitude;
});
_firestore
.collection('users')
.document('${loggedInUser.uid}')
.updateData({'location': GeoPoint(_latitude, _longitude)});
} catch (e) {
print(e);
}
}
Here's what I've been getting:
E/flutter ( 9187): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(Error performing updateData, NOT_FOUND: No document to update: projects/app-#####/databases/(default)/documents/users/CGyByl58ELc0zirlVjJpv5OWAc42, null)
So it is using the right uid ("CGyByl58ELc0zirlVjJpv5OWAc42")
Here's a screenshot from the Authentication tab of Firebase:
But what I'm trying to get is the name of the collection of this user in the database:
The user id is different than the document id, that's why you get that error since no document exists with the userId. You need to use the userId as the document id:
void addUser() async{
var firebaseUser = await FirebaseAuth.instance.currentUser();
Firestore.instance.collection("users").document(firebaseUser.uid).setData(
{
"age" : 38,
}).then((_){
print("success!");
});
}
Now you will have the userId as the document id and you can update the document using the userId
Here's my code to get current user documentsnapshot from database.
Future getCurrentUSerData() async {
final DocumentSnapshot doc = await userRef.document(currentUserId).get();
currentUser = MyUser.fromDocument(doc);
}
I got the currentUserId. there is no problem with that.
2.userRef is the reference to the users in firebase (final userRef = Firestore.instance.collection('users');)
but when I checked currentUser value, the value is returned as null.
Problem - How to get the current user data based on current user id?
Please change
final DocumentSnapshot doc = await userRef.document(currentUserId).get();
to
final DocumentSnapshot doc = await userRef.doc(currentUserId).get();
users>user Id then:
My aim is to return the user's key from the document and then be able to use that key in other functions.
getUsersKey() async {
final uid = await getCurrentUser();
Firestore.instance.collection('users').document(uid).get();
// Then I want to return the userKey feild
}
You can write the code below:
Future<void> getUsersKey() async {
final uid = await getCurrentUser();
DocumentSnapshot snapshot =
await Firestore.instance.collection('users').document(uid).get();
userKey = snapshot.data['userKey'] //you can get any field value you want by writing the exact fieldName in the data[fieldName]
}