realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.32k stars 2.15k forks source link

Allow Sorting across LinkingObjects Relationships #7413

Open bdkjones opened 3 years ago

bdkjones commented 3 years ago

Problem

Consider this relationship:

final class Parent: Object
{
    @Persisted var name: String
    @Persisted var kids: List<Child> 
}
final class Child: Object
{
    // There should only ever be one parent, but Realm does not provide singular LinkingObjects
    @Persisted var parents: LinkingObjects<Parent> = LinkingObjects(fromType: Parent.self, property: "kids")
    var parent: Parent? {
        return parents.first
    }
}

Now suppose I query a bunch of Child objects into a Results<Child>. I want to sort them by parent.name. This is not possible.

If you try to use the computed property parent in a SortDescriptor, you get an error that "parent does not exist". If you try to do parents.first.name, you get an error "Cannot sort on key path 'parents.first.name': property 'Child.parents' is of unsupported type 'linking objects'."

The only way to solve the problem is to abandon Realm, copy the objects to an Array and sort them. But then you lose the auto-updating nature of Results<T>.

Solution

Sorting should be allowed through computed properties and/or through LinkingObjects so that an entity can be sorted by a property of its parent.

This is not some edge-case functionality. It's really common. To use the standard Realm example, suppose you're displaying an NSTableView of Dog objects. One column in the table is "Owner's Name". You want to sort the Dogs by their Owner's name. You currently cannot accomplish that very simple task without either (1) ditching Realm collections as the datasource for the table or (2) bludgeoning the data model in the face with needless, duplicated properties that you must store and then keep in sync JUST to support sorting (for example, the Child object could have a string property called parentName that we must then keep in sync when the parent's property changes.)

How important is this improvement for you?

Would be a major improvement

leemaguire commented 3 years ago

Hi @bdkjones I see your issue, I will look into this.

leemaguire commented 3 years ago

Hi @bdkjones This is a feature we would like to implement, but as of now I cannot give a timeline. In the meantime a workaround would be to place an object link to the parent in the child like so:

final class Child: Object
{
    @Persisted var name: String
    @Persisted var parent: Parent?
}

This is going to require some careful memory management when the objects are first being created an in memory. But once they are retrieved from the Realm you will not get a retain cycle as the object accessors are lazily instantiated.

bdkjones commented 9 months ago

Was there an update on the timeline for this? It's been 2.5 years.

nirinchev commented 9 months ago

No. When we have an update, we'll share it in the issue.

3l3ktr0 commented 7 months ago

Hello, any update on this subject ?

I face the same issue and transforming Results to anArray to sort myself the data leads me to major issues like crashes like 'Object has been deleted or invalidated.' when I delete data of a @Published Array because ForEach will look into the Identifier of my Realm model that has been invalidated.

Even if I carefully delete the element of my array before removing it from the database, the async behaviour of Publish will delete the object before the UI updated.