Querying data present within a Firestore Database array in Flutter - firebase

I have my dataset modeled within the Firebase Firestore database as shown below:
I would like to retrieve and display the data based on the following criterias:
isAdmin is equal to true
isPerm is equal to true
userID sorted in descending order
I'm using the following versions of Firebase and Cloud Firestore packages:
firebase_core: ^0.5.0
cloud_firestore: ^0.14.0+2
I'm new to Flutter, I'm not sure, how I can achieve this. Really appreciate, if anyone could help me with this. Thanks for your help in advance.
I was able to retrieve the data as shown below, not sure how to sort it in descending order.
getUsers() async {
// _userCollection.doc('uGGuMfGS2DezVHHFASw4').where('userData', arrayContainsAny('isAdmin', isEqualTo: true)).get();
final _docRef = await _userCollection.doc('uGGuMfGS2DezVHHFASw4').get();
print(_docRef.data()['userData'].length);
for (var i = 0; i < _docRef.data()['userData'].length; i++) {
print(_docRef.data()['userData'][i]['username']);
print(_docRef.data()['userData'][i]['isAdmin']);
}
}

What you are trying to do with this data is not possible. Firestore does not have a way to query for specific map values nested in array fields. You will have to restructure this data to make it workable with Firestore.
One thing you can do is move all those array items into separate documents in a subcollection, then query the subcollection.
Another thing you can do is copy each nested value into an array to query with an array-contains type query.

Related

How to make a query from a nested collection in firestore using flutter

I have a nested collection in firestore that I want to make a query from it.
As you can see the first collection called 'businessUsers' and the nested one called 'campaigns',
If I make a query for a field in the 'businessUsers' it's working OK:
return FirebaseFirestore.instance.collection("businessUsers").where('xxx',
isEqualTo:filterBusinessResult ).snapshots().map(_businessListFromSnapshot);
but how can I make a query to 'campaigns' collection field?
I tried
return FirebaseFirestore.instance.collection("businessUsers").doc().collection("campaigns").where('campaignCategory', isEqualTo:filterBusinessResult ).snapshots()
.map(_businessListFromSnapshot);
but it wont work.
Its important to note, that I need all the data with 'campaignCategory' == filterBusinessResult
any idea?
It depends on whether you want to query a specific user's campaigns, or the campaigns of all users together.
If you want to query the campaigns of a specific user, you need to query under their document:
FirebaseFirestore.instance
.collection("businessUsers").doc("your user ID").
.collection("campaigns")
.where('campaignCategory', isEqualTo:filterBusinessResult)
So you have to know the ID of the businessUsers document here.
If you want to query across all campaigns subcollections are once, that is known as a collection group query and would look like this:
FirebaseFirestore.instance
.collectionGroup("campaigns")
.where('campaignCategory', isEqualTo:filterBusinessResult)
The results are going to documents from the campaigns collection only, but you can look up the parent document reference for each DocumentSnapshot with docSnapshot.reference.parent.parent.
When querying something, .doc() requires the id of the document you're trying to get. So it's failing because it doesn't know which document in the businessUsers collection you're trying to fetch a subcollection on. You probably want to use a .collectionGroup() query here. They let you query all subcollections at once (see documentation here). With FlutterFire specifically, it's going to be something like:
var snapshots = FirebaseFirestore.instance.collectionGroup("campaigns")
.where("campaignCategory", isEqualTo: filterBusinessResult)
.snapshots();

Flutter Firebase: Retrieve a list of documents, limited to IDs in an array?

I'm working on a Flutter app where each user can create projects, and share projects with other users. I've created a 'shares' collection, where each user's ID is a document, and within that document, all project IDs that have been shared with that user are collected like so, with a boolean that represents whether or not the share has been accepted yet:
Next, I created a collection of the projects themselves, like so:
Now, I'd like to query the 'projects' collection and return only the projects that are in a given user's 'shares' list. First off, how can I get each document in the share list's ID? And secondly, is it possible to compare that ID to the contents of a List using a .where() clause?
I've been trying something like this, but to no avail:
Stream<List<Map<String, dynamic>>> getListOfProjectsForUser({#required List<String> shares}) {
var ref = _firestore.collection('projects');
return ref
.where(shares, arrayContains: ref.id)
.snapshots()
.map((QuerySnapshot snapshot) => snapshot.docs.map((DocumentSnapshot doc) => doc.data()).toList());
}
I also tried this:
Stream<List<Map<String, dynamic>>> getListOfProjectsForUser({#required List<String> shares}) {
var ref = _firestore.collection('projects');
return ref
.where(shares, arrayContains: FieldPath.documentId)
.snapshots()
.map((QuerySnapshot snapshot) => snapshot.docs.map((DocumentSnapshot doc) => doc.data()).toList());
}
Is what I'm trying to do even possible? I've been messing with this for two days and my head's exploding. Any help would be greatly appreciated. Thanks in advance.
You'll need two operations.
Read the document for the user, to determine the list of project IDs.
Perform a in query for the project documents matching those IDs. The in operator accepts up to 10 IDs, so if you have more than 10 projects you'll need multiple queries and merge the results in your application code.
var citiesRef = db.collection("projects");
citiesRef.where(FieldPath.documentId, arrayContains: ['project1id', 'project2id']);
Also see:
The FlutterFire documentation for the where(field, whereIn:) operation
The FlutterFire documentation for the FieldPath.documentId field
First off, how can I get each document in the share list's ID?
For this, you're required to actually query the entire collection. You can iterate the results to collect the IDs of each document. There is no easy way to just get a list of IDs directly from web and mobile client code. See: How to get a list of document IDs in a collection Cloud Firestore?
And secondly, is it possible to compare that ID to the contents of a List using a .where() clause?
If you have a list of document ID strings in memory that could be any length, you will need to perform a query filtering projects for "projOwner" for each individual ID. There are no SQL-like joins in Firestore, so you can't simply join the two collections together with a single query.
Here's how you do a single one - you have to call out the name of the field to filter on:
firestore
.collection("projects")
.where("projOwner", isEqualTo: id)
If you have 10 or less share IDs in the list, you can use an "in" query to find matches from projects, and it will not work with any more.
firestore
.collection("projects")
.where("projOwner", whereIn: listOfIds)
So, if you think the list could ever be larger than 10, you should just start by performing individual queries for each share ID.
if 'arrayContains' is not working try 'whereIn'.
var citiesRef = db.collection("projects");
citiesRef.where(FieldPath.documentId, whereIn: ['project1id',
'project2id']);

How to fetch documents , in the order as their document ids are stored in some variable list/array , in cloud firestore firebase?

I have an array or list of name "A", in which there are document Ids. Now I want to bring documents from cloud firestore, in the order in which their document Ids are stored in the list "A".
"whereIn:" Only fetches documents in the order they are in collection of cloud firestore, but i want to fetch in order as mentioned in the list.
Also, I am using ".getDocuments()", in order to fetch data,So please mention, if there any other efficient way of fetching data,which supports offline,caching.As, there can be some 200 to 400 documents.
Code:
List A;//Not empty :), contains ordered document ids of the collection
QuerySnapshot snapshot = await someCollectionRef.where('/*somefieldname*/', whereIn: A).getDocuments();
List<Users> users = snapshot.documents.map((doc) => User.fromDocument(doc)).toList();//Here converting that snapshot data into list
please mention, if there is any other efficient way of fetching data as I am here using ".getDocuments()",which supports offline,caching.As, there may be some 200 to 400 documents.
Thanks for the help in advance :)
this should do what you want, just change the element you want to compare in the data document:
querySnapshot.documents.sort((a, b) {
return a.data['id'].compareTo(b.data['id']);
});
in the code above, i'm comparing the ID of these docs.

Firebase realtime database filtering data

so here i have
So I am making dating app, and now i come to the moment, where i need to create a list of people to match with for user.
So I need a firebase query to look in to gender and check if the people already matched, if yes it should not be included in the list.
I tried, filtering data by gender. How I should edit this query to check if they already matched?
Matches are displayed in users/{userID}/matches/{matchedUserID}
This is what i tried:
async createUserListAndNavigate() {
let genderTolook = 'female';
let data = firebase
.database()
.ref('users/')
.orderByChild('gender')
.equalTo(genderTolook);
data.once('value', snapshot => {
console.log(JSON.stringify(snapshot.val()));
});
}
You can use the array-contains-any query to check if the matches array already contains the user_id.
var users = db.collection("users");
users.where('tempuser.matches', 'array-contains-any', [<USER_ID_TO_MATCH>]);
Based on the result you can make further queries/operations. You could also combine this query with other queries.
See the documentation for further details.

Use Firestore autoID to retrieve and display data in Flutter

im new to flutter and dont know exactly what to search for this one but, can we use the auto generated ID like in the picture to retrieve all that data UNDER that ID? if so, how ? In a similar question that I stumbled upon, they use database.reference() but its a Realtime Database and not FireStore
Im using Firebase Cloud Firestore
There is no AutoId in firebase but here is a quick way to set as auto id
Forexample ;
1- create yourModel ( which one u gonna send as model to firebase )
2- DatabaseReference firebaseDatabase;
3- firebaseDatabase =FirebaseDatabase.instance.reference();
4- firebaseDatabase.child("table_name").push().set( yourModel.toJson() );
Also for getting data u can write code like that
var result= firebaseDatabase.child("table_name").once().then(
(DataSnapshot datasnapshot){
Map<dynamic,dynamic> values= datasnapshot.value;
values.forEach((key,value){
print("key:"+key+" value:"+value["name"]);
});
}
);
print(result);
I tried it and works great
Have a nice day !!!
I'm guessing you're asking about subcollections.
If you read a document (by its (auto-generated or not) key), you get back that document. You don't get back data from any subcollection. That will require a separate read operation for each subcollection under the document that you want to read.

Resources