Making queries offline on local snapshot copy of Firestore Snapshot Query - firebase

I have following fields in a document at Firestore
Category: Online, OnSite,
Status: true, false,
postTime: mm.dd.yyyy.hh.mm.ss
I am using following method to fetch the snapshot from Firebase with filter on Status & postTime.
Future getData() async {
QuerySnapshot qn = await FirebaseFirestore.instance
.collection("items")
.where("status", isEqualTo: true)
.orderBy("postTime", descending: true)
.get();
return qn.docs;
}
Now that I have qn with a copy of Firestore data, can I run more specific queries OFFLINE on qn where I can further filter it with Category ?
Purpose is: If the app user wants to further filter/sort some data then I do not want to consume data from Firestore for every query since the main data is already fetched.

Dart has a convenient method called where for iterable objects that you can utilize to filter in various ways.
https://api.flutter.dev/flutter/dart-core/Iterable/where.html
Example:
final filteredDocs = qn.docs.where((doc) => doc.data()['status'] == 'pending').toList();

Related

Flutter firestore add collection and data in document

I want to add data and collection both I am trying like this
Future<void> createRoom(collection, docid, data) async {
await FirebaseFirestore.instance
.collection(collection)
.doc()
.set(data)
.collection('messages');
}
But its showing error The method 'collection' isn't defined for the type 'Future'.
If you are trying to set a document in a sub-collection then first create a DocumentReference to that collection and then use set():
await FirebaseFirestore.instance
.collection(collection)
.doc("doc_id")
.collection('messages')
.doc("msg_id")
.set(data)
Do note that you should pass document ID in doc() else it'll generate a random ID every time instead updating existing one.
I want to add data and collection both
You don't need to create a collection explicitly if you are not adding a document yet. It'll be created at the time you add first document in collection. So try refactoring the code as shown below:
Future<void> createRoom(collection, docid, data) async {
await FirebaseFirestore.instance
.collection(collection)
.doc("doc_Id")
.set(data);
// simply add a document in messages sub-collection when needed.
}
Also checkout: How to create collection in Cloud Firestore from Javascript?

When exactly is a read on firebase firestore performed

I'm reading a lot about "how to minify firebase read actions" and now trying to implement a function that caches the data and only updates modified one.
(Project is made with Dart and Flutter)
For this purpose, lets assume i have a subcollection containing 10 documents, each holding at least the field "lastModified".
here's my example:
GetOptions _CACHE = GetOptions(source: Source.cache);
GetOptions _SERVER = GetOptions(source: Source.server);
DateTime lastModified;
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference collectionReference = firestore.collection("collection").doc("document").collection("collection");
Query lastModifiedQuery = collectionReference.orderBy("lastModified", descending: true);
QuerySnapshot snapshot = await collectionReference.get(_CACHE);
if (snapshot.docs.isEmpty)
{
QuerySnapshot querySnapshot = await lastModifiedQuery.limit(1).get(_SERVER);
if (querySnapshot.size > 0)
{
lastModified = querySnapshot.docs.first.get("lastModified");
} else {
lastModified = DateTime.now();
}
} else {
Query queryRefresh = collectionReference.orderBy("lastModified", descending: true).where("lastModified", isGreaterThan: lastModified);
}
Now i am unsure about the different calls.
I know that i am firing a read operation on every document if i call ".get()".
But does just creating a query also runs a database operation and, in my case, updates the cache?
Or do i have to run a ".get()" on the query and i am done?
Creating a query does not access the database yet. Only once you call get() or listen to onSnapshot will data be read from Firestore.

get data from both collection and it is sub collection in firestore with flutter

i have this database structure in Firestore:
this what inside places
how can i make a query in flutter to get all data inside Places sub-collection along with name from User collection, this code to get all places sub-collection data from every User collection :
Future<List<PlaceModel>> getPlaces() async {
List<PlaceModel> placesList = [];
// get all docs from user collection
var users = await udb.get();
for( var uid in users.docs) {
var userData = await udb.doc(uid.id).get();
var userPlaces = await udb.doc(uid.id).collection(placeTable).get();
userPlaces.docs.forEach((place) {
placesList.add(PlaceModel.fromMap(place.data()));
});
}
return placesList;
}
You can also use where() or orderby() methods to get data with some rules.
Firestore.instance
.collection("users")
.document(uid.id)
.collection(placeTable)
.where('fieldName', isEqualTo:name )
.snapshots()
A single query can only access a single collection, or a group of collection that have the same name. Firestore queries are shallow and don't read data from subcollections. If you need the data from the subcollection, you will have to execute an additional query to read it.

How to fetch data from firestore using .where(GreaterThan, and LessThan) condition. - Flutter

I'm trying to fetch data from firestore using the .where() condition.
Query adsRef = FirebaseFirestore.instance
.collection('All ads')
.where('adPrice',
isGreaterThanOrEqualTo: '2000')
.where('adPrice',
isLessThanOrEqualTo: '115000')
.limit(adsPerPage);
QuerySnapshot querySnapshot = await adsRef.get();
When using only one condition (eg: .where('adPrice',isGreaterThanOrEqualTo: '2000') ) works but dosen't fetch all documents[Just fetching random documents].
And when using both condtions it retruns null even though the DB has matching data.
Is there any other way to fetch data from firestore within two numbers? (in between 2000 to 115000)
Two inequality conditions are not valid in one firestore query. wrap you block of code in try catch and you will see the error.
Alternatively you can query both of your conditions separately and then merge the results like this:
void getAds() async {
List<Future<QuerySnapshot>> futures = [];
var firstQuery = FirebaseFirestore.instance
.collection('All ads')
.where('adPrice', isGreaterThanOrEqualTo: '2000')
.getDocuments();
var secondQuery = FirebaseFirestore.instance
.collection('All ads')
.where('adPrice', isLessThanOrEqualTo: '115000')
.getDocuments();
futures.add(firstQuery);
futures.add(secondQuery);
List<QuerySnapshot> results = await Future.wait(futures);
results.forEach((res) {
res.documents.forEach((docResults) {
print(docResults.data);
});
});
}
Please do try this and let me know if it works for you. Thanks

How to get data from subcollection in firestore using flutter?

i tried this .Sorry im a beginner.i cant put a document I'd in the unique I'd place as there are multiple documents under which userProducts collection comes. moreover new documents will keep generating as users increase.Inside every new document generated there's a subcollection created called userProducts.Is any other way ?
Future getProducts() async {
var firestore = Firestore.instance;
QuerySnapshot snapshot = await firestore.collection('products'). documents (doc id).collection('userProducts').getDocuments();
// .orderBy('timestamp', descending: true)
return snapshot.documents;

Resources