I am trying to query time with condition isGreaterThan, but it doesn't show data.
The code is correct, but I don't know problem.
I want to show data time isGreater selected time.
I think to there is problem in Geoflutterfire with condition isGreaterThan.
_setStream() async {
_locationData = await location.getLocation();
var pos = await location.getLocation();
double lat = pos.latitude!;
double lng = pos.longitude!;
print('timeeeeeeeee$_time');
int _ti = Timestamp.now().millisecondsSinceEpoch - 999 * 60 * widget.time;
var ref = await FirebaseFirestore.instance
.collection('now')
.where('gender', isEqualTo: widget.gender)
.where('time', isGreaterThan: _ti)
.orderBy('time', descending: true);
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
stream = radius.switchMap((rad) {
var collectionReference = ref;
return geo.collection(collectionRef: collectionReference).within(
center: center, radius: rad, field: 'location', strictMode: true);
});
setState(() {
isLoading = false;
});
stream = geo.collection(collectionRef: ref).within(
center: center,
radius: widget.distance,
field: 'location',
strictMode: true);
stream!.listen((List<DocumentSnapshot> documentList) {
documentList.forEach((element) {
print("from data .......element");
print(element.data());
final data = element.data() as Map<String, dynamic>;
final GeoPoint point = data['location']['geopoint'];
print("from data .......latitude");
print(point.latitude);
});
});
}
Firestore queries can only perform range conditions (>= and such) on a single field. When you use GeoFire, it already needs to perform this condition on the geohash value to perform the geoquery, so you can't perform a range condition on any other field.
If you want to understand why that is, I recommend watching this video on implementing geoqueries on Firebase's NoSQL databases.
If also recommend checking this answer I gave recently on adding an additional range filter to a geoquery, which covers common workarounds: Is it possible to query Firebase Firestore by both a location and age range?
Related
Query<Map<String, dynamic>> collectionReference
Type: Query<Map<String, dynamic>>
The argument type 'Query<Map<String, dynamic>>' can't be assigned to the parameter type 'CollectionReference<Object?>'.
We are trying to query our task collection and filter it based on topic, status, userid but we are getting the above error.
We are using the Geofire lib along with Firebase
Future<void> fetchTasksNearBy(double lat, double lng) async {
print('getting tasks in location');
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
double radius = 60; //in km
String field = 'location';
// Reading nearby tasks based on lat, lng parameters
try {
var collectionReference = tasksRef
.where('status', isEqualTo: 'Posted')
.where('ownerId', isNotEqualTo: widget.user!.id)
.where('category.subCategoryId', isEqualTo: widget.subCat);
Stream<List<DocumentSnapshot>> placesStream =
geo.collection(collectionRef: collectionReference).within(
center: center,
radius: radius,
field: field,
strictMode: true,
); // = false includes borderline places
await for (var doclist in placesStream) {
if (doclist.isNotEmpty) {
for (DocumentSnapshot ds in doclist) {
print('${ds.id} ${ds['title']}');
}
} else {
print('Nearby tasks do not exist in the database');
}
}
} catch (e) {
print(e);
}
}
I have a problem with the query with the condition isNotEqualTo does not work and does not show the values checked from the condition, note that I tried the condition isNotEqualTo and it worked
What is the problem
_setStream() async {
var pos = await location.getLocation();
double lat = pos.latitude!;
double lng = pos.longitude!;
var ref = await FirebaseFirestore.instance.collection('now')
.where('uid', isNotEqualTo: _user.uid).orderBy('uid');
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
stream = radius.switchMap((rad) {
var collectionReference = ref;
return geo.collection(collectionRef: collectionReference).within(
center: center, radius: rad, field: 'location', strictMode: true);
});
setState(() {
isLoading = false;
});
stream = geo.collection(collectionRef: ref).within(
center: center, radius: 2000, field: 'location', strictMode: true);
stream!.listen((List<DocumentSnapshot> documentList) {
documentList.forEach((element) {
print("from data .......element");
print(element.data());
final data = element.data() as Map<String, dynamic>;
final GeoPoint point = data['location']['geopoint'];
print("from data .......latitude");
print(point.latitude);
});
});
}
Even though NotEqual query is available in firebase, it was made available late in flutter plugin. The best option is to fetch all to a list and remove unwanted elements from the list
I have to query the geoflutterfire data with a Stream.
But I would like to use this in a Future in a ChangeNotifierprovider to be able to wait until the Stream has all data.
I never built a Future with a Stream in it before. What do I have to return?
When I don't have a return and just do notifyListeners(), the function runs forever. So I just put in return true.
Is there a better way to do this?
Future<void> fetchPlacesNearBy(double lat, double lng) async {
print("GETTING FIRESTORE PLACES");
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
double radius = 5; //in km
String field = 'geo_location';
// Reading nearby places based on lat, lng parameters
try {
Stream<List<DocumentSnapshot>> placesStream =
geo.collection(collectionRef: _placesRef).within(
center: center,
radius: radius,
field: field,
strictMode: false,
); // = false includes borderline places
await for (var doclist in placesStream) {
topWikiPlacesAroundUser2 = [];
if (doclist.length > 0) {
for (DocumentSnapshot ds in doclist) {
/// Init place model
WunderkPlace pl = WunderkPlace.fromMap(
ds.data(), ds.get('geo_location.geopoint'));
topWikiPlacesAroundUser2.add(pl);
}
} else {
print('Nearby places do not exist in the database');
}
notifyListeners();
return true;
}
} catch (e) {
print(e);
return false;
}
}
I'm trying to call a function which will populate a list by reading a stream. Means, it will read a stream and add values to a list and finally, the list will be returned by the function.
The problem is, when I'm using await for to read the stream, the code after the await for is not getting executed. And I tried to use listen, then it's not waiting to finish reading the stream. The code after the listen is getting executed even before the stream is read completely.
Following in my code -
Future<List<Map<String, dynamic>>> getNearestDriver(Stream<List<DocumentSnapshot>> driverWithinRangeStream, GeoPoint source) async {
print("Get Nearest Driver Called");
List<Map<String, dynamic>> driverAvailableList = [];
await for (List<DocumentSnapshot> documentList in driverWithinRangeStream){
documentList.forEach((DocumentSnapshot document) async {
String driverIDVar = document.data['driverid'];
GeoPoint pos = document.data['position']['geopoint'];
var point = geo.point(latitude: pos.latitude, longitude: pos.longitude);
double distanceVar = point.distance(lat: source.latitude, lng: source.longitude);
int distanceInMeter = (distanceVar*1000).round();
Map<String, dynamic> newDriverAvailable = {"driverId": driverIDVar, "distance" : distanceInMeter};
driverAvailableList.add(newDriverAvailable);
});
print(driverAvailableList); /* <- I get the data here */
}
print(driverAvailableList); /* <- But I don't get the data here. This code is not even being executed. */
}
Please let me know what's wrong here.
Would you mind to try
try{
await for (List<DocumentSnapshot> documentList in driverWithinRangeStream){
await Future.forEach(documentList, (DocumentSnapshot document) async {
try{
String driverIDVar = document.data['driverid'];
GeoPoint pos = document.data['position']['geopoint'];
var point = geo.point(latitude: pos.latitude, longitude: pos.longitude);
double distanceVar = point.distance(lat: source.latitude, lng: source.longitude);
int distanceInMeter = (distanceVar*1000).round();
Map<String, dynamic> newDriverAvailable = {"driverId": driverIDVar, "distance" : distanceInMeter};
driverAvailableList.add(newDriverAvailable);
}catch(error){
throw "throw from documentList, Error:$error";}
});
}
}catch(error){
print ("catch in driverWithinRangeStream, Error:$error");}
I have this code trying to query some data from Firestore using GeoFlutterFire, but for the sake of efficiency I want to fetch the list of ids only once, then use it to fetch the rest of the data from Firebase Database.
This is the code in question:
class _StartScreenState extends State<StartScreen> {
List ids = ['abc'];
#override
void initState() {
super.initState();
print('ids ${ids}');
}
_initState() async {
Firestore _firestore = Firestore.instance;
List ids1 = [];
Geoflutterfire geo = Geoflutterfire();
var location = new Location();
var pos = await location.getLocation();
GeoFirePoint center = geo.point(latitude: pos.latitude.toDouble(), longitude: pos.longitude.toDouble());
var collectionReference = _firestore.collection('locations');
var geoRef = geo.collection(collectionRef: collectionReference);
return ids1.add(geoRef.within(center: center, radius: 50, field: 'position', strictMode: true).first.then((value) {
value.map((doc) {
if (doc.data.isNotEmpty) {
print('doooc id here ${doc['id']}');
ids1.add(doc['id']);
print(ids1);
}
}).toList();
setState(() {
ids = ids1;
print('setting state to ids ids print: ${ids.}');
});
}));
}
Like I said, my intent is to fetch the Ids and once I have the list check if there's some related data in Firebase, but I'm not sure this is the way I should do it and there's something that I don't know how to awoid; When I print the list I get the following result:
setting state to ids ids print: [Instance of 'Future',
3esdWesqrTD_123_3dssds3, sQWdsda23dsad_da21]
Can anyone tell me why I have this Instance of 'Future' in my List and how can avoid it, please?
I have not tried to run your code, but I suspect the issue starts with the statement
return ids1.add(geoRef.within(center: center, radius: 50, field: 'position', strictMode: true).first.then((value) {
As you can see, you are adding something ids1.add(...) that looks like it needs to await: geoRef.within(...).first.(...). I don't find the ids1.add(...) call needed in the return statement. Try removing it, and see how it goes.