Query and algorithms using firestore db? - firebase

I am currently trying to figure out how to match and/or compare data in firestore database. Lets say I have 10 apples. My apple has the color red. I want to be able to compare my color to the other 10 apples and then match only with the ones who has the color red (there are 2 apples with the color red). How can I achieve this while using firestore database as the main database for all apples?
Firebase Db looks something like this:
apple1 is red and should match with apple5. The rest are different colors. When the user press the search button, it should filter the firestore Db and only match with the adequate respons (in this case apple5 which is also red) How can I achieve this? Do I need to use a third party library to create this algorithm or can it be done in kotlin since it is to my understanding that some features does not work with firestore Db? Appreciate any feedback!

That's a pretty straightforward query, 'fetch documents where the value of field color is red'. Try:
db.collection("apples")
.whereEqualTo("color", "red")
.get()
.addOnSuccessListener { documents ->
for (document in documents) {
Log.d(TAG, "${document.id} => ${document.data}")
}
}
.addOnFailureListener { exception ->
Log.w(TAG, "Error getting documents: ", exception)
}
Checkout the documentation for more query examples that Firestore supports.

Basically, you can use Queries to match a certain condition and get all documents.
For your case, you can use the following code snippet to get the data based on color
try {
AsyncSnapshot<QuerySnapshot> data = firestore.collection("hubs")
.where("color", isEqualTo: "red")
.get();
final docs = data.data!.docs;
docs.forEach((e)=>{
//each firestore document
});
}
Find the official documentation here.

Related

How can I check if a document contains a value inside a Firestore array?

I'm using Flutter and Firestore , where is this database I'm trying to be able to see if a value exists inside an array, but I only found solutions that didn't work for me, sometimes they were in another language, but I want to be able to see if a value exists inside an array in a document.
for example, I want to check if the user id userID1 is inside the array miembros marked in red in the following image
the idea is that I can do an if to add the value userID1 if it doesn't exist in the miembros array.
actually thank you very much for any help
If you just need to check if an array contains a specific value, then you can use arrayContains as shown below:
FirebaseFirestore.instance
.collection('grupos')
.where('miembros', arrayContains: 'ValueToCheck')
.get()
.then(...);
However, you can use arrayUnion() instead that will add the value if it's missing else it won't:
Firestore.instance
.collection('grupos')
.document('grupoId4')
.updateData({ 'array':FieldValue.arrayUnion('ValueToAddInArray') });
I found the solution, it turns out that the following can be done when one knows the document ID.
firestoreRef.where(FieldPath.documentId, isEqualTo: docID).snapshots();
by adding in where the FieldPath.documentId, isEqualTo: docID we can search based on the document id, after this we can do a forEach or whatever is estimated in the case.

Problem implementing search on my flutter app through cloud firestore

I want to implement search on my flutter app through cloud firestore database (by 'NAME' field of documents). I came across with the query below but sadly this query is case sensitive.
If I want to search 'Apple', then I will have to type 'Apple'. Typing 'apple' or 'APplE' won't give any result.
FirebaseFirestore.instance
.collection('test')
.where(
'NAME',
isGreaterThanOrEqualTo: searchVal,
isLessThan: searchVal
.substring(0, searchVal.length - 1) +
String.fromCharCode(searchVal
.codeUnitAt(searchVal.length - 1) +
1),
)
.snapshots()
Please suggest any way to make this searching efficient and not case-sensitive.
According to this related thread, Firestore cannot currently perform case-insensitive queries. In this case, the comment on your post applies, so you should create an alternate name field in Firestore that contains all lower case names. From the client side, all queries should be made lower case with a function such as toLowerCase() so that letter cases completely match on both ends.

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']);

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.

How to read a firestore value in a map?

I'm trying to read the value for exp_date in my flutter app as seen in this picture:
The field/value pair is in a map called Card which is in a sub collection called sources . I can read the value by putting in the DocId for the sources collection(the other docId is the firebase user uid) with the following:
StreamBuilder(stream: Firestore.instance.collection('stripe_customers').document(userId).collection('sources').document('qRvDob75kTzhT3').snapshots(),builder: (context,snapshot){
if(!snapshot.hasData){
return new Text("Loading");
}
var userDocument = snapshot.data;
return new Text(userDocument["card"]['exp_year'].toString());
},),
But obviously this isn't very practical. How do I access the Card map value without knowing the document id?
There are two ways to get the contents of a document:
Know its entire, unique path.
Make query against a known collection to get matching documents.
If you don't know the id required by #1, you will have to try #2. But since you don't seem to have have a way to filter the documents in that collection, you will have to fetch ALL of the documents. This is probably not what you want to do for scalability purposes.
Give some consideration about how you want to find the data in Firestore before you write the documents.

Resources