how to obtain a particular document from a collection in firestore using Flutter - firebase

I am new to dart and so obviously to flutter... I did integrate firestore and did programming in android java.. and so I am finding it a little bit difficult to understand what means what in android java and flutter in regards to Firestore.
e.g. whats the alternative to addOnCompleteListener(android java) in flutter?

Regarding your question about how to get the document from collection you can refer the following code
DocumentReference documentReference =
Firestore.instance.collection("users").document("John");
documentReference.get().then((datasnapshot) {
if (datasnapshot.exists) {
print(datasnapshot.data['email'].toString(););
}
else{
print("No such user");
}
consider users collection has a document named as John with data as email: "j#gmail.com".
You can find the documentation very useful and almost all the functions are present for the flutter too. Just you should be able to do error and exception handling.
oncomplete() and listen() functions might be very helpful.
Hope it helped.

Related

Firebase cross-service Security Rules not working in application

I'm trying to use the new Firebase cross-service Security Rules (https://firebase.blog/posts/2022/09/announcing-cross-service-security-rules) but I having some problems with Storage Rules accessing to Firestore data.
The problem seems to be with userIsCreator() function
match /certification/{certificationId}/{fileId} {
function userIsCreator() {
let certification = firestore.get(/databases/(default)/documents/certifications/$(certificationId));
return firestore.get(certification.data.creatorRef).id == request.auth.uid;
}
allow read, write: if userIsCreator()
}
The content of the Firestore Document is:
{
"data": {
othersValues,
"creatorRef": "/databases/%28default%29/documents/users/CuutSAtFkDX2F9T8hlT4pjMUByS2"
}
"id": "3EhQakDrsKxlacUjdibs"
"__name__":
"/databases/%28default%29/documents/certifications/3EhQakDrsKxlacUjdibs"
}
The creatorRef variable is a reference to a Firestore Document to user. Inside Users collection, the doc id is the UID of an user, so I'm obtaining the creatorRef of an item and then checking if the id of that user collection referenced is the same UID that user logged in.
The same function is working for Firestore Rules to avoid updating certification document if not the creator, without any problem.
It seems to be a problem calling to firestore.get to creatorRef after obtaining it but it not make sense!
Tested:
If I use Firestore Storage Rules validator, it is not failing and it says I have access to that resource from the UID typed in the tester (for other UID is failing as expected). But in my app, even logged in with creator user is getting permission error.
If changing the function to only one call directly to the Users collection id (return firestore.get(/databases/(default)/documents/users/CuutSAtFkDX2F9T8hlT4pjMUByS2).id == request.auth.uid;), it is working in the tester and my app. But it isn't a solution because I need to get first the Users collection ref for the creator!
For original function in the tester It's getting the variables as expected and returning true if simulate the creator UID! But for any reason, in the real app access it is getting unauthorized if making both calls!
Firebaser here!
It looks like you've found a bug in our implementation of cross-service rules. With that said, your example will create two reads against Firestore but it's possible to simplify this to avoid the second read.
Removing the second read
From your post:
return firestore.get(certification.data.creatorRef).id == request.auth.uid;
This line is a bit redundant; the id field is already contained in the certification.data.creatorRef path. Assuming you are indeed using Firestore document references, the format of creatorRef will be /projects/<your-project-id>/databases/(default)/documents/users/<some-user-id>. You can therefore update your function to the following:
function userIsCreator() {
let certification = firestore.get(/databases/(default)/documents/certifications/$(certification));
let creatorRef = certification.data.creatorRef;
// Make sure to replace <your-project-id> with your project's actual ID
return creatorRef ==
/projects/<your-project-id>/databases/(default)/documents/users/$(request.auth.uid);
}
I've tested this out in the emulator and in production and it works as expected. The benefit of doing it this way is you only have to read from Firestore once, plus it works around the bug you've discovered.

.once() doesn't seem to work / recognized while working with Flutter & Firebase

I am trying to fetch some data from FireStore and store it in a local list to be displayed later in the form of cards. I have seen many tutorials where people have used .once() to fetch data.
Now, when I am trying to do the same then getting error like the word isn't recognized.
#override
void initState() {
super.initState();
CollectionReference dbRefItem = FirebaseFirestore.instance.collection("items");
***dbRefItem.once().then***
}
I cant seem to find any documentation if it has been deprecated or am I doing something wrong! Hovering cursor on the error says
"The method 'once' isn't defined for the type 'CollectionReference'.
Try correcting the name to the name of an existing method, or defining
a method named 'once'."
.get() did the same job as .once()
However, .once() syntax is not being accepted by Flutter's latest SDK while worked on the previous one. Have raised a ticket with Flutter Dev forum.

flutter firebase querysnapshot: case insensitive method in dart code

I'm flutter user with firebase connected.
I'm trying to call list of users from cloud firestore with querysnapshot when users call search feature and then string submitted. What I've tried is snippet below:
Future<QuerySnapshot> allUsers = usersReference
.where("profileName",
isGreaterThanOrEqualTo: str)
.getDocuments();
setState(() {
futureSearchResults = allUsers;
});}
The problem is I have to make 'profileName' called by querysnapshot 'case insensitive'. For example, profileName 'HELLO WORLD' in cloud firestore must be printed as 'hello world' in my android studio flutter console. So i need a flutterFire method to convert all uppercase characters from cloud firestore to lowercase characters. Unfortunately, i couldn't find simple property to set case-insensitive from flutterFire plugIn.. ]:
Furthermore, what i'm trying to call from firestore is not a bunch of strings but certain form of document which is going to be converted to certain custom class written in dart. It made me unavailable with neat dart methods like toLowerCase().
If anyone know method in dart code to change uppercase characters from cloud firestore to lowercase, please share your knowledge.
Clear answers so appreciated!! Thank you in advance [:
Firestore does not offer case-insensitive queries. If you need to query for strings using any case, you should store a "canonical" version of the string in Firestore, the make the client code use that for all queries. So, for example, you could store all strings as lowercase in the database, then require your client code to convert all strings to lowercase before querying.

How to create custom index for firestore query

I need to be able to retrieve some data from my cloud firestore database where certain conditions are met and then order that data but I am unable to get my query to work. I've read that if you simply run the query then your log should provide you a link to automatically create the custom index but unfortunately within my flutter logs or the android studio logcat i'm not getting any links. I know you can create the custom indexes manually in the firebase console so i'm happy to do this but I dont know how I would create the index for this.
firestore.collection('users').where('organisation_id', isEqualTo: _authenticatedUser.organisationId)
.orderBy('first_name').getDocuments()
I just need to know how to create the composite index for this query so that it will work in my app
I was able to get a link in my console log by surrounding the firestore query with a try catch and printing out the platform exception which generated the direct link, thanks to Dougs answer
try {
snapshot = await firestore.collection('users').where(
'organisation_id', isEqualTo: _authenticatedUser.organisationId)
.orderBy('first_name').getDocuments();
} catch(e){
print(e);
}

Using .numChildren() in AngularFire

I'm trying to use .numChildren() in AngularFire, but not sure I'm doing it correctly.
function getServiceProviders(serviceId) {
var serviceProviders = ref.child('services').child(serviceId).child('providers');
return serviceProviders.numChildren();
}
I'm getting the following error:
TypeError: e.numChildren is not a function
Not sure if this is due to me using Browserify, or I'm just trying to access numChildren incorrectly.
Any help is appreciated. Thanks in advance!
Your code snippet doesn't use AngularFire, it only uses the Firebase JavaScript SDK. Although your project undoubtedly uses AngularFire, it doesn't relate to this question.
When you look at the documentation for the .child() method in the Firebase JavaScript SDK, you'll see that it returns a Firebase reference. And if you look further into that class, you should notice that it doesn't have a numChildren method.
numChildren is only available on a DataSnapshot object, which you get in any of the on(... event handlers.
So:
serviceProviders.on('value', function(snapshot) {
console.log(snapshot.numChildren());
}
Since the snapshot will be loaded asynchronously, you cannot return the number of children from getServiceProviders. See my answer to this question for a broader explanation of that: Asynchronous access to an array in Firebase

Resources