getDataInArea<T> function
Provides as Stream of lists of data items of type T
that have a location field in a
specified area sorted by the distance of to the areas center.
area
: The area that constraints the query
source
: The source FireStore document collection
mapper
: mapping function that gets applied to every document in the query.
Typically used to deserialize the Map returned from FireStore
locationFieldInDb
: The name of the data field in your FireStore document.
Need to make the location based search on the server side
locationAccessor
: As this is a generic function it cannot know where your
location is stored in you generic type.
optional if you don't use distanceMapper
and don't want to sort by distance
Therefore pass a function that returns a valur from the location field inside
your generic type.
distanceMapper
: optional mapper that gets the distance to the center of the
area passed to give you the chance to save this inside your item
if you use a distanceMapper
you HAVE to pass locationAccessor
clientSideFilters
: optional list of filter functions that execute a .where()
on the result on the client side
distanceAccessor
: if you have stored the distance using a distanceMapper
passing
this accessor function will prevent additional distance computing for sorting.
sortDecending
: if the resulting list should be sorted descending by the distance
to the area's center. If you don't provide loacationAccessor
or distanceAccessor
no sorting is done
Implementation
Stream<List<T>> getDataInArea<T>(
{@required Area area,
@required Query source,
@required DocumentMapper<T> mapper,
@required String locationFieldNameInDB,
LocationAccessor<T> locationAccessor,
List<ItemFilter<T>> clientSitefilters,
DistanceMapper<T> distanceMapper,
DistanceAccessor<T> distanceAccessor,
bool sortDecending = false}) {
assert((distanceAccessor == null) || (distanceMapper != null && distanceAccessor != null),);
var query = buildQuery(
collection: source, constraints: getLocationsConstraint(locationFieldNameInDB, area));
return getDataFromQuery<T>(
query: query,
mapper: (docSnapshot) {
// get a real objects from FireStore
var item = mapper(docSnapshot);
double distance;
if (locationAccessor != null)
{
distance = area.distanceToCenter(locationAccessor(item));
}
if (distance != null) {
// We might get places outside the target circle at the corners of the surrounding square
if (distance > area.radiusInKilometers)
{
return null;
}
if (distanceMapper != null)
{
return distanceMapper(item, distance);
}
}
return item;
},
clientSitefilters: clientSitefilters != null ? ()=>clientSitefilters..insert(0,(item) => item != null) : [(item) => item != null],
orderComparer:
distanceAccessor != null // i this case we don't have to calculate the distance again
? (item1, item2) => sortDecending
? distanceAccessor(item1).compareTo(distanceAccessor(item2))
: distanceAccessor(item2).compareTo(distanceAccessor(item1))
: locationAccessor != null
? (item1, item2) => sortDecending
? area
.distanceToCenter(locationAccessor(item1))
.compareTo(area.distanceToCenter(locationAccessor(item2)))
: area
.distanceToCenter(locationAccessor(item2))
.compareTo(area.distanceToCenter(locationAccessor(item1)))
: null);
}