How to use FieldPath.of() in Firebase Firestore with Flutter - firebase

I'm trying to update a nested document field in Firebase Firestore, but when I use the FieldPath instance, It raises a compiler exception
Map _map = {
'name': 'vin',
'quantity': 2,
'costPrice': 12000,
};
var fieldPath = new FieldPath(['categories', 'branch']);
final CollectionReference _storeRef =
FirebaseFirestore.instance.collection('stores');
_storeRef.doc('6').update({fieldPath: _map});
How do I update a nested document Field using the Firebase FieldPath instance

The DocumentReference.update method requires a Map<String, dynamic> as it's first parameter and the reason for the compiler error is because you're trying to pass a FieldPath object instead of a String.
You can reduce the values of the FieldPath into a String and use that as the path for the update method.
Update this:
_storeRef.doc('6').update({fieldPath: _map});
to this:
_storeRef
.doc('6')
.update({'${fieldPath.components.reduce((a, b) => '$a.$b')}': _map});
This basically means the same as:
_storeRef
.doc('6')
.update({'categories.branch': _map});

Related

Firebase receive documentID when adding and updating documents to firebase with flutter

I am adding a new document to my firestore group 1, and use the new documentID of that group to update two other documents. Afterwards, I'd like to save the documentID from group 1 in a variable in order to pass it to my widgets.
How can I receive and save the documentID when adding a new document to group 1 without causing an extra firestore read? I don't understand why the code below works except for
valueId = value.documentID
Thanks
onPressed: () {
firestore.collection('Gruppe').add({
'Group': messageTextController.text.trim(),
'Gruppenersteller': loggedInUser.uid,
'Gruppenmitglieder': FieldValue.arrayUnion([
loggedInUser.email,
widget.userEmail,
]),
'Angelegt': FieldValue.serverTimestamp(),
}).then((value) => {
firestore
.collection('Nutzer')
.document(loggedInUser.uid)
.updateData({
'Slates': FieldValue.arrayUnion([value.documentID])
}),
firestore
.collection('Nutzer')
.document(widget.userNutzerId)
.updateData({
'Slates': FieldValue.arrayUnion([value.documentID])
}),
valueId = value.documentID,
});
print('valueID');
print(valueId);
You can get the random ID of a document before it's added like this:
val docRef = firestore.collection('Gruppe').doc()
val docId = docRef.documentID;
Then you can go on and create the document with set():
docRef.set(...)
In your code above, I would expect that print(valueId) to not print the assigned value of value.documentID, because add() and then() are asynchronous and return immediately with a Future. In fact, any function that returns a Future will do so immediately. The callback you provide to then() will be invoked some time later, after the operation is complete. So, effectively, your code is trying to print the document ID before it's been assigned. That's why I'm suggesting that you get it immediately of the reference instead of trying to get it later.

Object Mapping in Flutter to Realtime DB Firebase

I want to save my List with Objects in Firebase Realtime DB. The Problem is, that when I save my objects there, they dont have an auto generated key, their key is 0, 1, 2,... :
I am mapping my Poll object this way:
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'allowBarChart': allowBarChart,
'allowPieChart': allowPieChart,
'description': description,
'custom-questions': customQuestions != null
? List<dynamic>.from(customQuestions.map((x) => x.toJson()))
: [],
'choice-questions': choiceQuestions != null
? List<dynamic>.from(choiceQuestions.map((x) => x.toJson()))
: [],
};
My Question is: how to do it, so the key of each value is not 0,1,2,3,... It should be auto generated from firebase, for example: 1fdDfasLPO3g. I hope you know what I mean.
Thanks in advance!
When the Firebase SDK encounters a List it is mapped to a JSON array, which is stored with sequential numeric indices, as seen in the screenshot you shared. There is no way to change this mapping.
If you want to store items with Firebase's push keys (which start with -M at the moment), you should generate those in your application code (by calling push()), and store the questions in a Map<string, dynamic>.

How to convert Firebase Map to Dart Map?

This fails silently in Dart:
Map<String,String> dartMap = doc.data['keyForFieldthatContainsMap'];
doc is a firebase document (type DocumentSnapshot) that has a field "keyForFieldthatContainsMap" which contains a Map.
doc.data is of type:
Map<String,dynamic>
At runtime doc.data['keyForFieldthatContainsMap'] has the type:
_InternalLinkedHashMap<dynamic, dynamic>
from which I don't know how to access the keys and values.
I'm using the package:
import 'package:cloud_firestore/cloud_firestore.dart';
I'm looking for a way to read map fields just like I can read string, number, boolean,... fields from firebase.
Try to change your dartMap to Map<dynamic,dynamic>. Your error might occour cause you cant now which types your Map in Firestore has.

Firestore: Getting a subcollection from a DocumentSnapshot

I'm using Firestore for backend for a Flutter project, and the database is nested to have sub-collections under documents.Here's the structure:
I have the data found from the Root collection, and from there I'm trying to get the sub-collection, but I can't figure how to.
There should be a get() method available but I'm not getting any.
Here's the code for the function:
void _getNext(DocumentSnapshot doc) async {
int v = doc.data.length;
String id = doc.documentID;
print('length = $v \t id= $id');
await doc.reference.get().then((val){
val.data.forEach((k, v){
print('k = $k & v = $v');
});
});
await doc.data.forEach((k,v){
print("new k = $k, v = $v");
});
await doc.reference.collection(id).getDocuments().then((val){
val.documents.forEach((e){
print("another k = $e");
});
});
}
And the only response I get from pressing the "Literature" document (from the root collection) is this:
I/flutter (13395): length = 0 id= Literature
There are several sub collections to this document but the returned length is zero. The other blocks of code work fine when I added dummy data to the fields, but that's not needed in my case.
Thank You for your help.
collection() returns a CollectionReference. As you can see from the API docs, neither CollectionReference, nor it superclass Query have a method called get(). I suspect you want to use getDocuments() instead.
There is no get() method for CollectionReference, you need a DocumentReference.
There is nothing wrong with the current situation, you probably want to use getDocuments() since there are no subcollections under your collection, but documents
Notice the alternating pattern of collections and documents. Your collections and documents must always follow this pattern. You cannot reference a collection in a collection or a document in a document.
from: Hierarchical Data

How to use query .document using firebase ui

I'm using this Firebase-UI
I have Users (collection), uid (document), and array for image url.
This is my Firebase schema
How to use document query so I can get specific user and get imageUrl?
Query query = FirebaseFirestore.getInstance()
.collection("users")
.document(auth.currentUser!!.uid)
Error:
None of the following functions can be called with the arguments supplied.
setQuery(Query, (snapshot: DocumentSnapshot) → Profile) defined in com.firebase.ui.firestore.FirestoreRecyclerOptions.Builder
setQuery(Query, SnapshotParser) defined in com.firebase.ui.firestore.FirestoreRecyclerOptions.Builder
setQuery(Query, Class) defined in com.firebase.ui.firestore.FirestoreRecyclerOptions.Builder
this works, but i just want to know if i can use .document
val query = FirebaseFirestore.getInstance()
.collection("users")
.whereEqualTo(FieldPath.documentId(), auth.currentUser!!.uid)
There is no way to use the following line of code:
Query query = FirebaseFirestore.getInstance()
.collection("users")
.document(auth.currentUser!!.uid)
Once because this is not the way you are declaring variables in Kotlin. And second because when calling document() function on a CollectionReference object it returns a DocumentRefence object and not a Query object.
So you can simply use:
val document = FirebaseFirestore.getInstance()
.collection("users")
.document(auth.currentUser!!.uid)
And the document object will now of type DocumentReference.

Resources