Open jadar opened 2 years ago
Hi @jadar,
Depending on how you are storing the location data, you could make use of our Type Projections feature for your use case. Here's a blog post showcasing it .
If you could show us your Realm model and your usage we may be able to help you further.
@leemaguire
I recently switched to storing locations by using type projection to story a CLLocationCoordinate2D
as an embedded Coordinate
object.
class Boundary: Object {
@Persisted
var centerCoordinate: CLLocationCoordinate2D?
@Persisted
var geometry: String? // geojson
...
}
class Location: Object {
@Persisted
var boundary: Boundary
...
}
I'd like a sorted collection of Location
objects sorted by distance to the current location from location.boundary.centerCoordinate
.
We have plans on implementation of Geospatial Indexing but it's not yet any close.
At the moment you may take a look at RealmGeoQueries It's not recent but you may have an idea how to achieve this.
We have plans on implementation of Geospatial Indexing but it's not yet any close.
At the moment you may take a look at RealmGeoQueries It's not recent but you may have an idea how to achieve this.
I have looked at RealmGeoQueries but it doesn't include support for live collections or change notifications, which is what I am looking for (see my "Problem" above.) It only gives you a sorted array.
I realize Geospatial indexing might be far away on the road map. That is why I've suggested the half-way work around by allowing you to have a collection type that sorts based on a computed property while also maintaining all the state necessary to continue vending change notifications.
@jadar you can sort using SortComparator
and you can use computed property there
something like this. Sure you want to add some math
class Point: Object {
@Persisted var x: Float
@Persisted var y: Float
var referencePt: (Float, Float) = (0, 0)
var distance: Float { get { sqrt((x - referencePt.0)*(x - referencePt.0) + (y - referencePt.1)*(y - referencePt.1)) } }
}
extension Point: Comparable {
static func <(lhs: Point, rhs: Point) -> Bool {
lhs.distance < rhs.distance
}
}
let points = realm.objects(Point.self)
points.forEach { pt in
pt.locale = (2, 0)
}
print(points.sorted())
@pavel-ship-it
Thanks for your suggestion. In your example, is points.sorted() going to be of the Results
type? Also, is there a way I can sort on the collection on the distance
keypath directly, rather than the comparable implementation? I'm running into exceptions both when I try to sort based on "self" and on "distance".
Hi @jadar, until we support geospatial queries / sorting points.sorted()
will not return Results<Point>
but instead a Swift Array. Also because distance
is a computed property it will not work with our sorting mechanism.
Problem
I need to sort a Realm collection by geo-spatial distance based on a location property on a Realm Object. I'd also like this collection to receive update notification for insertions, deletions, and updates.
Solution
Obviously, this can't happen in the database engine unless the engine supported some kind of complex sort descriptor, or unless it was built to support geo-spacial operations in the first place. I know that geo-spatial features have been on the roadmap for quite some time, but it seems that other efforts have taken precedence.
I think the best way forward to support my use-case would be to add a special
Results
type that wraps aRealmCollection
, performs the sorting operation in-memory based on a comparator, and forwards updates for the newly sorted indices like a normalRealmCollection.
This allows users to opt-in to lower performance when a specific feature is required.The use of the API would look something like this:
How important is this improvement for you?
Would be a major improvement