Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support projections #947

Open
cmelchior opened this issue Aug 2, 2022 · 9 comments
Open

Support projections #947

cmelchior opened this issue Aug 2, 2022 · 9 comments

Comments

@cmelchior
Copy link
Contributor

Similar to the ideas expressed here: realm/realm-java#5426 and as exposed by Cocoa here: realm/realm-swift#7375

Projections would decouple the model classes (Database Entity) from how the data is being used in the UI (View Model classes). Which would solve a few use cases

  • Reduce the coupling between layers. A common criticism is that Realm is spreading throughout the entire app as you use the model classes.

  • More type-safe API as projections would only expose data actually needed.

  • Data classes could be used as projection classes as the data is read-only.

  • Preload all data on a background thread, instead of relying on lazy-loading. As the expectation is that all projection fields are being read, we could also bulk-fetch these as an optimization. Something that isn't really possible with our model classes.

We would need to iterate on the exact API and functionality, but something like this:

public class Child: RealmObject {
  var name: String
}

public class Dog: RealmObject {
  var name: String = ""
  var age: Int = 0
  var owner: Child? = null
}

// Decoupled projection classes
@Projection(Dog::class) // Required so we can validate fields at compile time
data class DogData1(
  val name: String
)

@Projection(Dog::class)
data class DogData2(
  val name: String,
  @FieldProjection("owner.name") // Collect linked properties
  val owner: String
)

// Cocoa has "live" projection classes on which you can attach change listeners. Unclear if that fits Kotlin, but could look like this:
@Projection(Dog::class)
data class DogData: RealmProjection(
  val: name: String
)

// Queries should probably still be on model classes, but could be mapped directly to projections. 
realm.query<Dog>("name BEGINWITH 'Fido'").asFlow(DogData1::class).collect { data: DogData1 -> updateView(data) }

}

// They could also be used to update in the Realm
val userData = DogData(name = "newName")
realm.write {
  find("name = 'Fido'")!!.updateWith(userData)
}
@Burtan
Copy link

Burtan commented Aug 3, 2022

Would generating the projections from the entity classes allow to have pure data classes without realm dependencies? I'm currently doing this manually. The biggest problem is using flows instead of RealmLists which behave differently when comparing equality of data classes. Maybe I need a custom class that implements the List interface using flows...

@cmelchior
Copy link
Contributor Author

That is one of the things we want to explore. It would be possible, but would result in some runtime overhead as we would need to calculate/validate that we can actually copy data correctly.

Would even adding a single annotation to the data class be too much, ie.?

@Projection(Dog::Class)
data class DogViewModel(val name: String, val age: Int)

@cmelchior
Copy link
Contributor Author

Can you also elaborate on The biggest problem is using flows instead of RealmLists which behave differently when comparing equality of data classes. What exactly are you trying to achieve?

@Burtan
Copy link

Burtan commented Aug 3, 2022

I want to be able to keep observing changes on oneToMany relations in my pure data classes which are generated from the realm classes. So I convert the RealmList to a Flow and then to a StateFlow which I then keep in my data class. However when comparing data classes for equality List behaves different to StateFlow<List>. With lists its actual content is compared while StateFlows are compared by instance (like arrays which generate IDE warnings when used in data classes for that reason).
I think the best way to solve that is to use a wrapper around StateFlows similiar to RealmList and comparing that wrapper compares the latest list values.

@Burtan
Copy link

Burtan commented Aug 3, 2022

Personally I don't mind having @Projection as an annotation but when trying to clean the ui from a realm dependency does it matter to have just an annotation as a dependency or classes or whatever?

@helmysaeed
Copy link

You should unify the MongoDB Atlas( Kotlin driver)UI data layer with Atlas Device SDK UI data layer to increase sharing code, especially for jetpack compose multiplatform

@helmysaeed
Copy link

Any update in this Issue

@helmysaeed
Copy link

Any update on this Issue

@sirambd
Copy link

sirambd commented Oct 8, 2024

Hello, It's a really cool idea, and it can really help us with our projects, so any update on this issue ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants