within method
Stream<List<DocumentSnapshot<Object?> > >
within({
- required GeoFirePoint center,
- required double radius,
- required String field,
- bool strictMode = false,
query firestore documents based on geographic radius
from geoFirePoint center
field
specifies the name of the key in the document
Implementation
Stream<List<DocumentSnapshot>> within({
required GeoFirePoint center,
required double radius,
required String field,
bool strictMode = false,
}) {
final precision = Util.setPrecision(radius);
final centerHash = center.hash.substring(0, precision);
final area = GeoFirePoint.neighborsOf(hash: centerHash)..add(centerHash);
Iterable<Stream<List<DistanceDocSnapshot>>> queries = area.map((hash) {
final tempQuery = _queryPoint(hash, field);
return _createStream(tempQuery).map((QuerySnapshot querySnapshot) {
return querySnapshot.docs
.map((element) => DistanceDocSnapshot(element, null))
.toList();
});
});
Stream<List<DistanceDocSnapshot>> mergedObservable =
mergeObservable(queries);
var filtered = mergedObservable.map((List<DistanceDocSnapshot> list) {
var mappedList = list.map((DistanceDocSnapshot distanceDocSnapshot) {
// split and fetch geoPoint from the nested Map
final fieldList = field.split('.');
final data =
distanceDocSnapshot.documentSnapshot.data() as Map<String, dynamic>;
var geoPointField = data[fieldList[0]];
if (fieldList.length > 1) {
for (int i = 1; i < fieldList.length; i++) {
geoPointField = geoPointField[fieldList[i]];
}
}
final GeoPoint geoPoint = geoPointField['geopoint'];
distanceDocSnapshot.distance =
center.distance(lat: geoPoint.latitude, lng: geoPoint.longitude);
return distanceDocSnapshot;
});
final filteredList = strictMode
? mappedList
.where((DistanceDocSnapshot doc) =>
doc.distance! <=
radius * 1.02 // buffer for edge distances;
)
.toList()
: mappedList.toList();
filteredList.sort((a, b) {
final distA = a.distance!;
final distB = b.distance!;
final val = (distA * 1000).toInt() - (distB * 1000).toInt();
return val;
});
return filteredList.map((element) => element.documentSnapshot).toList();
});
return filtered.asBroadcastStream();
}