This question already has answers here:
"The operator '[]' isn't defined" error when using .data[] in flutter firestore
(6 answers)
Closed 3 months ago.
I would like to recover data in my firebase database but it does not work.
void _userData() async {
DocumentReference documentReference = FirebaseFirestore.instance
.collection("Users")
.doc("axelduf2006#gmail.com");
documentReference.get().then((datasnapshot) {
data = datasnapshot.data;
return print("pseudo: ${data['pseudo']}");
});
}
my log console
I would like to know the value contained in pseudo in my database.
Change data with data() to get the Map<String, dynamic> of your document.
void _userData() async {
DocumentReference documentReference = FirebaseFirestore.instance
.collection("Users")
.doc("axelduf2006#gmail.com");
documentReference.get().then((datasnapshot) {
data = datasnapshot.data() as Map<String, dynamic>; // set it like this
return print("pseudo: ${data['pseudo']}");
});
}
Passing the data will pass the definition of Map<String, dynamic> Function ( () => Map<String, dynamic> ), not the actual Map<String, dynamic> of the document data.
Related
My below code is returning an empty list, even though it SHOULD return data corresponding to my data stored in my firestore database. Also to note: The otherUserId print statement is not getting printed. How can I fix this issue?
Future<List<String>> getChattingWith(String uid) async {
List<String> chattingWith = [];
try {
// create list of all users user is chatting with
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('users', arrayContains: uid)
.get();
for (final room in rooms.docs) {
final users = room['users'] as Map<String, dynamic>;
final otherUserId = users['uid1'] == uid ? users['uid2'] : users['uid1'];
print("otherUserId999: $otherUserId");
chattingWith.add(otherUserId);
}
print("chattingWith: $chattingWith");
return chattingWith;
} catch (error) {
print("error: $error");
return [];
}
}
This part of your code does not match your data structure:
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('users', arrayContains: uid)
.get();
Your users is a Map and not an array, so arrayContains won't work here. As said in my answer to your previous question, you have to use dot notation to test nested fields:
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('users.uid1', isEqualTo: uid)
.where('users.uid2', isEqualTo: otherValue)
.get();
That 👆 is closest to what you tried in your previous question: Firestore conditional array query. It performs an AND condition on the uid1 and uid2 subfields of users.
If instead you want to get all rooms that the user is a participant in, you need an (additional) field that is an array with the UIDs of all participants.
participantUIDs: ["uid1", "uid2"]
Then you can do:
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('participants', arrayContains: uid)
.get();
I made a User model class that is working fine for handling data from Firebase Auth and Firestore. Would it cause any issues to feed the User model with data that looks like this: [{uid: uid1, modifiedDate: 1663118207725, createDate: 1663118207725, username: username1}]? The goal is to download that data, push it through the User model to extract only the uid and username, then write to the groupMembers collection. I'm not sure if it's recommended practice to use models so loosely like this. Should you only pass data that matches the exact definition of the model through it?
groupMembers:
uid: uid1
username: username1
User model
class User {
final String uid;
String username = ''; //Empty during Firebase Auth. Afterwards, this should be filled with the value from Firestore
User({
required this.uid,
required this.username
});
User.fromJson(Map<dynamic, dynamic>? json): //Transform JSON into User
uid = json?['uid'] as String,
username = json?['username'] as String;
Map<dynamic, dynamic> toJson() => <dynamic, dynamic>{ //Transforms User into JSON
'uid': uid,
'username': username,
};
}
void addFriendsToGroup(String groupID, List friends) {
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference groupMembersCollection = firestore.collection('groups').doc(groupID).collection('groupMembers');
friends.forEach((element) {
final user = UserModel.User.fromJson(element);
final data = <String, String> {
'uid': user.uid,
'username' : user.username,
};
groupMembersCollection.doc().set(data);
});
}
I am learning how to use "Firestore" with BLoC pattern in Flutter. I am following this tutorial by Sagar Suri. https://medium.com/codechai/when-firebase-meets-bloc-pattern-fb5c405597e0. However, this tutorial is old and I am trying to remove bugs and update it for learning purpose. I am facing 2 issue in it. First issue is related with 'updateGoal' function. In example, he copied goals value from collection , cast it into the String and then updated the value. I am getting an error here. Anybody can help me, how I can extract goals value from users, copy into Map, cast it and then update. . This is what I am trying to do.
Future<void> uploadGoal(String title, String documentId, String goal) async {
DocumentSnapshot doc =
await _firestore.collection("users").doc(documentId).get();
Map<String, String> data = doc.data()! as Map<String, String>;
/****/
//Getting error here "The operator '[]' isn't defined for the type 'Object? Function()'."
Map<String, String> goals = doc.data["goals"] != null
? doc.data["goals"].cast<String, String>()
: null;
/****/
if (data != null) {
data[title] = goal;
} else {
data = Map();
data[title] = goal;
}
return _firestore
.collection("users")
.doc(documentId)
.set({'goals': data, 'goalAdded': true}, SetOptions(merge: true));
}
Similar issue, I am facing in removeGoal function.
void removeGoal(String title, String documentId) async {
DocumentSnapshot doc =
await _firestore.collection("users").doc(documentId).get();
Map<String, String> data = doc.data()! as Map<String, String>;
//How to remove goals title from collection here
goals.remove(title);
if (goals.isNotEmpty) {
_firestore
.collection("users")
.doc(documentId)
.update({"goals": goals});
} else {
_firestore
.collection("users")
.doc(documentId)
.update({'goals': FieldValue.delete(), 'goalAdded': false});
}
}
Anybody can help me? Thanks.
This looks wrong:
Map<String, String> data = doc.data()! as Map<String, String>;
While all the keys in your document are strings, the goals value is an object/dictionary instead of a string. So at best you can cast it to:
Map<String, dynamic> data = doc.data()! as Map<String, dynamic>;
Once you do that, the statement you commented out to get the goals field should work, but it it doesn't: provide an updated in to your question with the updated code, and the exact error message and stack trace you get.
I'm trying to get a specific field called "specie" from a document in a Firebase collection. I am trying as follows but I have an error of type 'Future ' is not a subtype of type 'String'. What am I doing wrong?
Repository method:
getSpecie(String petId) {
Future<DocumentSnapshot> snapshot = petCollection.document(petId).get();
return snapshot.then((value) => Pet.fromSnapshot(value).specie);
}
Entity method:
factory Pet.fromSnapshot(DocumentSnapshot snapshot) {
Pet newPet = Pet.fromJson(snapshot.data);
newPet.reference = snapshot.reference;
return newPet;
}
factory Pet.fromJson(Map<String, dynamic> json) => _PetFromJson(json);
Pet _PetFromJson(Map<String, dynamic> json) {
return Pet(json['name'] as String,
specie: json['specie'] as String);
}
I found a solution. No needed fromJson() method, I only changed the repository method:
Future<String> getSpecie(String petId) async {
DocumentReference documentReference = petCollection.document(petId);
String specie;
await documentReference.get().then((snapshot) {
specie = snapshot.data['specie'].toString();
});
return specie;
}
Try this..
getSpecie(String petId) async{
Future<DocumentSnapshot> snapshot = await petCollection.document(petId).get();
return snapshot.then((value) => Pet.fromSnapshot(value).specie);
}
This is how I learned to get documents from firestore
https://medium.com/#yasassandeepa007/how-to-get-sub-collection-data-from-firebase-with-flutter-fe1bda8456ca
I trying to get the new created document id after data has been stored to firebase database, but get error
E/flutter (20333): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The method 'listen' was called on null.
E/flutter (20333): Receiver: null
E/flutter (20333): Tried calling: listen(Closure: (String) => void)
send_data_bloc
_repository
.addOrder(order)
.listen((documentId) => print(documentId));
repository
#override
Observable<String> addOrder(Order order) {
var a = endpoints.collectionEndpoint.add(order.toJson());
a.then((val) {
return Observable.fromFuture(val.documentID());
});
endpoints
#override
get collectionEndpoint => _firestore
.collection(collectionName)
.document(this.id)
.collection(orderCollectionName);
Ideally you should return the future from the repository and await for the future on the bloc. Let me try to give a full code snippet here. It would be something like this:
send_data_bloc
final documentId = await _repository
.addOrder(order);
print(documentId);
return documentId;
repository
#override
Future<String> addOrder(Order order) {
return endpoints.collectionEndpoint.add(order.toJson());
endpoints
#override
get collectionEndpoint => _firestore
.collection(collectionName)
.document(this.id)
.collection(orderCollectionName);
Here
a.then((val) {
return Observable.fromFuture(val.documentID());
});
you are returning the observable within the then function, i believe this is not the expected behavior.
One thing you should do to improve your code quality and readability is to just user async/await. The function on the repository can be rewrited like that:
#override
Observable<String> addOrder(Order order) async {
var documentID = await endpoints.collectionEndpoint.add(order.toJson());
return Observable.fromFuture(val.documentID());
Try this. This should do the trick.
Whats the reason why you are using Observables? Is this a firebase thing?
You could adjust to:
final var documentId = await _repository.addOrder(order);
print(documentId)
i had the same problem here is a snippet of how i approached it
//notice im using add while referencing the document reference
final DocumentReference documentReference=await Firestore.instance.collection('jobs').add({
'jobid':"",
});
then get your id from documentReference
final String jobIdd=documentReference.documentID;
after getting the id now you can add your document to cloud firestore
Firestore.instance.collection('jobs').document(jobIdd).setData({
'category': category,
'description': description,
'datePosted': formattedDate,
'postedby': userid,
'jobid':jobIdd,
});