How can I fetch data only from specific date using firestore? - date

I am trying to put all of the documents from a collection in a list using firestore, I want documents that were only uploaded in a certain year.
There is a field in all of the documents called "dateAdded", which stores the date formatted in 'dd-MM-yyyy'.
for testing I only have 3 documents, 2 uploaded in 2020 and 1 in 2019
QuerySnapshot querySnapshot= await Firestore.instance
.collection('Deceased')
.where("dateAdded",
isGreaterThanOrEqualTo:"01-01-"+year )
.where("dateAdded",isLessThanOrEqualTo:"31-12-"+year )
.getDocuments();
I have tried to do it this way, only the first condition works. Any suggestions?

There is something called startAt or startAfter and endAt or endBefore which you can use, to use that you must first orderby the field you want to use query on so, here I am using startAt and endAt which should give you the result you want which I believe is the record for a whole year
QuerySnapshot querySnapshot= await Firestore.instance
.collection('Deceased')
.orderBy('dateAdded')
.startAt([DateTime(year,1,1,0,0,0)])
.endAt([DateTime(year,12,31,23,59,59])(
.getDocuments();

it looks like you are storing data as a string. I suggest to store the data in seconds like this
final dateNow = DateTime.now();
final int seconds = (dateNow.millisecondsSinceEpoch ~/ 1000);
Once you have the data in firebase as second it is super easy to handle it
QuerySnapshot querySnapshot= await Firestore.instance
.collection('Deceased')
.where("dateAdded",
isGreaterThanOrEqualTo:xxxxxxx)
.where("dateAdded",isLessThanOrEqualTo:yyyyyy )
.getDocuments();
xxxxxxx and yyyyyy need to be an int. Look at https://www.epochconverter.com to understand how epoch time work
As an example, if you want to capture all record in 2019 you should first determine the epoch time for the 1st of Jan 2019 and then the time in second for the 31st of Dec 2019. If you use the website you will get the following
1st Jan 2019 = 1546300800
31st Dec 2019 = 1577836799
So your code should look like this
QuerySnapshot querySnapshot= await Firestore.instance
.collection('Deceased')
.where("dateAdded",
isGreaterThanOrEqualTo: 1546300800)
.where("dateAdded",isLessThanOrEqualTo: 1577836799 )
.getDocuments();

Related

can't show data of the last day in month from the cloud firestore in flutter

i'm trying to get data filtered by month, the user selects the month and the ui should get updated based on that selection. Everything works pretty fine unless it does not show the data of the last day of January (31st).
Here is a snippet of code with which i'm getting data:
stream: FirebaseFirestore.instance
.collection('interventions')
.where('userId', isEqualTo: user!.uid)
.where('date_iv',
isGreaterThanOrEqualTo:
DateTime(myTime!.year, myTime!.month, 1))
.where('date_iv',
isLessThanOrEqualTo:
DateTime(myTime!.year, myTime!.month + 1, 0))
.snapshots(),
Noting that myTime is the selected date chosen by the user. Any suggestions on how to fix this?

How do I query on the Flutter app for products added to Firebase today

I am trying to develop a stock management application on Flutter. I have integrated Firebase into the app and I can view the data on the app. My collection and documents are as follows:
There are products added on different dates in the database, but I want to filter the products added today. No products are found when I type a query like this:
var response = await FirebaseFirestore.instance
.collection('sayim')
.where('sirket', isEqualTo: sirket)
.where('tarih', isLessThanOrEqualTo: DateTime.now())
.where('tarih', isGreaterThanOrEqualTo: DateTime.now().day - 1)
.get();
I want to list all the products from the beginning of the day until now. How should I edit the query?
Just create a new date from now
DateTime now = new DateTime.now();
DateTime date = new DateTime(now.year, now.month, now.day);
and use that in your query
var response = await FirebaseFirestore.instance
.collection('sayim')
.where('sirket', isEqualTo: sirket)
.where('tarih', isLessThanOrEqualTo: now)
.where('tarih', isGreaterThanOrEqualTo: date)
.get();

Cloud Firestore QuerySnapshot Where function field not supported

I am using Cloud Firebase on my android app and I want to filter my documents using where function to avoid unnecessary billing cost, my problem is instead of using document field inside my where function I prefer model to filter my data due to multiple advantage, then I try below code, but it trough error of
"'field is String || field is FieldPath || field == FieldPath.documentId': Supported [field] types are [String] and [FieldPath].,"
I try this
final authPhoneNo = Utils.formatPhoneNo(phoneNo!);
CollectionReference receiptCollection = FirebaseFirestore.instance
.collection('example');
QuerySnapshot querySnapshot;
querySnapshot = await receiptCollection.orderBy('Date', descending: true).where((e){
Utils.formatPhoneNo(MainData.fromJson(e.data()).userPhoneNo!);
}, isEqualTo: authPhoneNo).get();
formatPhoneNo
static formatPhoneNo(String phoneNo) => phoneNo.replaceAll(RegExp(r"\D"), "")
.substring(
(phoneNo.replaceAll(RegExp(r"\D"), "").length) - 9,
(phoneNo.replaceAll(RegExp(r"\D"), "").length)
);
It through error on where((e)
'field is String || field is FieldPath || field == FieldPath.documentId': Supported [field] types are [String] and [FieldPath].
From the code you provided, I see that you want to filter data using where and a formatter function formatPhoneNo, but this is not how it works according to the official documentation:
// Create a reference to the cities collection
final citiesRef = db.collection("cities");
// Create a query against the collection.
final query = citiesRef.where("state", isEqualTo: "CA");
As you can see, the first parameter on the where clause refers to the field you want to filter and the second one refers to the query operation you want to perform (in this case, isEqualTo) and the reference value (in the example, the string "CA").
In your case, the right way to do the query would be as follows:
querySnapshot = await receiptCollection.where('phoneNo', isEqualTo: authPhoneNo).get();
To avoid the use of a formatter, which leads to unnecessary processing time every time it is called and; in this case could lead to format every result until the desired value matches the condition if its done without the where Firebase function, I would recommend to sanitize your data before saving it to Firebase as recommended in this article:
2. Standardize phone number formatting
When you capture telephone data, either directly from the customer or via an ingress from a data supplier, you should standardize the telephone number format. Ideally, you should use the industry-standard E.164 format
...
If you prefer to display a telephone number in a nice to read human format you can still store the number in your database in E.164 format but present the number on the screen in a friendly format.
Doing this way, you could filter your data saved in Firebase using simple and compound queries as shown in the Firebase documentation.

Using fields in a document for another query

I have 2 collections, one called Timeline and one called Posts. The first one is very simple, having 2 fields: 'PostId' and 'OwnerId', while the second one is a little bit more complex but it is not important for the purpose of my question.
Using 'OwnerId' and 'PostId' I can get a specified post in the collection Posts.
What I want to do is getting all the docs in timeline of a specified user, for each doc use it to get the post infos in Posts collection, and order the posts in descending timestamp, but I can't find a smart and effective way to do so.
To get all the docs of a specified user in Timeline I write:
QuerySnapshot snapshot = await timelineRef
.doc(currentUserID)
.collection('timelinePosts')
.get();
And to get a specified post from Posts collection I write:
QuerySnapshot snapshot = await postsRef
.doc(ownerId)
.collection('userPosts')
.doc(postId)
.get();
How can I mix these two to get the result I want? Thank you
There is no concept of a server-side join in Firestore, nor is there a way to filter the documents returned based on information in documents in another collection. All Firestore queries can do is evaluate the literal data in the candidate documents (through an index) and filter based on that.
So you will either have to duplicate the data to filter on in each userPosts document, or perform a so-called client-side join - with the latter being the most reasonable option for this use-case as far as I can see.
You'll end up with individual get() calls for the documents, or a bunch in in queries on the FieldPath.documentId() you get from timelinePosts, and then merge the results in your application code.
At the moment I found a solution that is not very elegant but at least is working:
QuerySnapshot snapshot = await timelineRef
.doc(widget.currentUser.userID)
.collection('timelinePosts')
.orderBy('timestamp', descending: true)
.get();
List<TimelineItem> timelineItems =
snapshot.docs.map((doc) => TimelineItem.fromDocument(doc)).toList();
List<PostWidget> postsTemp = [];
for (var element in timelineItems) {
DocumentSnapshot documentSnapshot = await postsRef
.doc(element.ownerId)
.collection('userPosts')
.doc(element.postId)
.get();
postsTemp.add(PostWidget(Post.fromDocument(documentSnapshot)));
}
I added timestamp field to my timelinePosts, created a class to contain the data from the first query, and then I did a second query based on the parameters I got on the first one for each doc.
Hopefully I'll find a more efficient solution but at the moment I use this

how to delete document by field inside collection inside document inside collection on firestore

I have Doctor collection when each doctor (represent by his email ) has a collection called patients_waiting.
Now, what I'm trying to do is delete one document from the paitents_waiting collection by field calls patients containing his email.
but I tried many solutions and none of them works for me now.
what I have tried to do :
Firestore.instance
.collection("Doctors")
.document(doctorEmail)
.collection("paitents_waiting")
.document(paitentEmail)
.delete();
now it's not good because the document is saved in uid and not by email but I tried to play with the where function but with no success.
how do I found this document by email and delete him?
I will mention that I'm doing it on flutter, but I think it doesn't matter.
as long as you have the patient's email address you can search with and delete it
Firestore.instance
.collection("Doctors")
. document(doctorEmail)
.collection("paitents_waiting")
.where('patient', isEqualTo:paitentEmail )
.get().then((value) => value.docs.single.reference.delete())
Nb: you are using an old version of firestore
Inside your paitents_waiting collection, the documents are NOT named according to patient email, they are randomly generated Firebase IDs. Take a closer look.
Firestore.instance
.collection("Doctors")
.document(doctorEmail)
.collection("paitents_waiting")
.document(paitentEmail) //this in your Firebase isn't an email, it's "xaErf43Asd..etc"
.delete();
If you want to follow this approach, which should be working otherwise, when you want to create a patient waiting document, use .set instead of .add, and set the document id to your pateint's email, like this:
Firestore.instance
.collection("Doctors")
.document(doctorEmail)
.collection("paitents_waiting")
.document(paitentEmail)
.set({your patient data here});
This should get things working for you.
To delete all patients for a doctor by the email you can use a combination of Firestore query and batch updates. The first one we need to get all patients with the same email and the other to delete them. A function for that would look like this:
Future<void> deletePatiensForDoctor(String docEmail, String patEmail) async {
WriteBatch batch = FirebaseFirestore.instance.batch();
QuerySnapshot querySnapshot = await Firestore.instance
.collection("Doctors")
.document(docEmail)
.collection("paitents_waiting")
.where('email', isEqualTo: patEmail)
.get();
querySnapshot.docs.forEach((doc) {
batch.delete(doc.reference);
});
return batch.commit();
}