I want to implement OR condition in flutter using the multiple where(); method but this returns AND condition.
Following is my code for query
Future<Stream<QuerySnapshot>> getOrders() async {
return FirebaseFirestore.instance
.collection("Orders")
.orderBy("timestamp")
.where("isCredentialUploaded", isEqualTo: true),
.where("isTransactionDone", isEqualTo: true)
.snapshots();
}
But this makes the AND Condition, like this
if(isCredentialUploaded && isTransactionDone)
Is there any way I can get the OR condition in Firebase Firestore?
Result i want:
if(isCredentialUploaded || isTransactionDone)
In the official documentation of Firebase & Flutter we notice that after using the query we must use get() instead of snapshot().
Try this code:
Future<Stream<QuerySnapshot>> getOrders() async {
return FirebaseFirestore.instance
.collection("Orders")
.orderBy("timestamp")
.where("isCredentialUploaded", isEqualTo: true),
.where("isTransactionDone", isEqualTo: true)
.get();
}
Related
I want two streams to be combined as one result and then return it from my function. I have two streams coming from firebase. So I have to merge data1 into data2, something like concatenation of both the streams and then return. What i have acheived so for is:
Future<Stream<QuerySnapshot>> getMsgs(userId, toId) async {
var data1 = await _fireStore
.collection(_collection)
.where('messageFrom', isEqualTo: userId).where('messageTo', isEqualTo: toId)
.orderBy('createdOn', descending: true)
.snapshots();
var data2 = await _fireStore
.collection(_collection)
.where('messageFrom', isEqualTo: toId).where('messageTo', isEqualTo: userId)
.orderBy('createdOn', descending: true)
.snapshots();
// I have tried this, but this will be the list
return [data1, data2];
// I have tried this, but didn't worked
return StreamZip([data1, data2]);
}
Any help would be appreciated.
the probleme in my code is whenever i add the orderby my code stops working and the data is not displaying even when i don't get any errors
here's the stream i sued :
Stream<QuerySnapshot> searchData(String textEntered) async* {
var _search = FirebaseFirestore.instance
.collection("users")
.doc(sharedPreferences!.getString("uid"))
.collection("inventaire")
.doc(widget.model!.InventoryID)
.collection("produits").where('BarCode', isGreaterThanOrEqualTo: textEntered).orderBy('LastUpdate', descending: true)
.snapshots();
yield* _search;
}
I'm guessing now, as there isn't much to go on. But you are probably missing an index for the query.
Check your logs if you get anything like: " The query requires an index."
You can read more about it at:
https://firebase.google.com/docs/firestore/query-data/indexing
Another alternative is using a StreamController to return a modified stream, that way you could refactor the code into a listen:
Stream<QuerySnapshot> searchData(String textEntered) {
var controller = StreamController<QuerySnapshot>();
FirebaseFirestore.instance
.collection("users")
.doc(sharedPreferences!.getString("uid"))
.collection("inventaire")
.doc(widget.model!.InventoryID)
.collection("produits").where('BarCode', isGreaterThanOrEqualTo: textEntered).orderBy('LastUpdate', descending: true)
.snapshots().listen((QuerySnapshot qSnapshot) {
controller.add(qSnapshot);
});
return controller.stream;
}
Using the StreamController could even allow you to map the documents out of the QuerySnapshot returned on the listen callback handler and instead returning a list of PODO objects already mapped as opposed to the QuerySnapshot. My two cents.
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
In Dart/Flutter and learning Firebase Firestore... I'm using the following method to test before creating UI:
_testFireStore() async {
var result = Firestore.instance
.collection('users')
.where('uid', isEqualTo: 'IvBEiD990Vh0D9t24l2GCCdsrAf1')
.snapshots();
await for (var snapshot in result) {
for (var user in snapshot.documents) {
print('main.DEBUG: ' + user.data.toString());
}
}
}
It works as expected -- the print statement is executed initially, but also subsequently in real-time every time any field is updated in the document in the Firestore database.
How can this code be changed such that the snapshot is only retrieved once -- not "subscribed/listened" to... and thus we don't waste bandwidth on unwanted/unneeded data and the print statement is only executed once?
Firestore.instance.collection(...).where(...) returns a Query object. It has a method called getDocuments() that executes the query and gives you a Future with a single set of results.
var query = Firestore.instance
.collection('users')
.where('uid', isEqualTo: 'IvBEiD990Vh0D9t24l2GCCdsrAf1');
query.getDocuments().then((QuerySnapshot snapshot) {
// handle the results here
})
Or use await to get the QuerySnapshot, since getDocumets() returns a Future.
Use getDocuments(), to retrieve all the documents once:
_testFireStore() async {
var result = await Firestore.instance
.collection('users')
.where('uid', isEqualTo: 'IvBEiD990Vh0D9t24l2GCCdsrAf1')
.getDocuments();
print(result.documents.toString());
}
I have a method to return some data from FireStore, which is used for pagination in my Flutter app.
static Future<QuerySnapshot> getAllItems({int count: 12, dynamic lastKey}) {
if (lastKey != null) {
return Firestore.instance
.collection('uploads')
.where('active', isEqualTo: true)
.where('purge', isEqualTo: false)
.startAfter([lastKey])
.orderBy("active_time", descending: true)
.where('active_time', isLessThanOrEqualTo: DateTime.now())
.limit(count)
.getDocuments();
} else {
return Firestore.instance
.collection('uploads')
.where('active', isEqualTo: true)
.where('purge', isEqualTo: false)
.orderBy("active_time", descending: true)
.where('active_time', isLessThanOrEqualTo: DateTime.now())
.limit(count)
.getDocuments();
}
}
When lastKey value is not passed, all works fine. But when I pass the string value of lastKey, I get the below error.
cursor position is outside the range of the original query
The field active_time is a TimeStamp type in FireStore. Index is created for the same.
Since active_time is a DateTime, lastKey should also be a DateTime.
From the Docs on startAfter
Takes a list of values, creates and returns a new Query that starts
after the provided fields relative to the order of the query.
https://pub.dartlang.org/documentation/cloud_firestore/latest/cloud_firestore/Query/startAfter.html
Let me document the issue I faced.
The issue was due to the difference of data type. The Firebase database and my dart variable type was different.. ie.. DateTime and Timestamp. After fixing this, the code started to work.