realm-dart
realm-dart copied to clipboard
Access RealmObject property name and mapToName, for use in Realm .query
Description
We build Realm
.query
's dynamically, for example when allowing users within the Flutter UI to filter/sort/search a Realm
model/collection via .query
- allowing the user to filter by XYZ params, etc by clicking on checkboxes, etc. Currently the 'keys' in the
.query
have to be hard coded using the@MapTo
key from theRealmObject
property, which is not ideal from a maintenance perspective. I.e.final hobbits = fellowshipOfTheRing.members.query('first_name == "Hobbit"');
To get over this 'hard coding', it would be great if we could access the RealmObject
property (as a string) and related @MapTo property (as a string) as follows:
-
p.firstName.name
// outputs stringfirstName
-
p.firstName.mapToName
// outputs stringfirst_name
(@MapTo property forp.firstName
) -
p.firstName.mapToNameOrName
// outputs no 2 above, falls back to option 1 if no 2 @MapTo does not exist
Or it may be better to p.firstName.reamlName
(or similar) which outputs whatever the property is in the Realm
local DB...i.e. as .query
essentially needs this whether its no 1 or 2 above.
This allows us to take advantage of darts strict typing when building Realm
.query
's, which would be amazing;
// i.e. p.firstName.name
would output firstName
as a string
Option 1: final hobbits = fellowshipOfTheRing.members.query('${p.firstName.name} == "Hobbit"');
or
// i.e. p.firstName.mapToName
would output first_name
as a string (i.e. the p.firstName
@MapTo
)
Option 2: final hobbits = fellowshipOfTheRing.members.query('${p.firstName.mapToName} == "Hobbit"');
Either route would work very well. There are also lots of other use cases for this...such as dynamically building CSVs from RealmResults
, please see https://github.com/realm/realm-dart/issues/1076
To add to this re .query
params in embedded objects/lists
It would also be good if we could access embedded arrays/lists via dot notation (or by some other way to give the same effect as the above two options). So for example (we have not tested .query
with params within embedded lists/objects yet so we are 'assuming' this is possible) if we could:
// i.e. {{p.friends.friends.name }}would output friends.firstName
as a string
Option 1: final hobbits = fellowshipOfTheRing.members.query('${p.friends.firstName.name} == "Hobbit"');
or
// i.e. p.friends.firstName.mapToName
would output friends.first_name
as a string (i.e. the p.firstName @MapTo
)
Option 2: final hobbits = fellowshipOfTheRing.members.query('${p.friends.firstName.mapToName} == "Hobbit"');
How important is this improvement for you?
Would be a major improvement
We do have plans to support LINQ (as known from .NET) style queries. Would allow you to do queries like:
realm.all<Fellow>().where((f) => f.race == 'Hobbit');
or something similarly expressive. Tracked here #781. But I must warn that it is not right around the corner.
ooo that sounds amazing @nielsenko - ok will keep an eye on this and thanks for the heads up. This LINQ does not help the use case in this issue https://github.com/realm/realm-dart/issues/1077 as the user dynamically builds the query based on filters selected, so for #1077 it would have to be a query string?
The realmObject.property.name
syntax is not easily achieved, since the realmObject.property
is itself a getter for the value of said property. Maybe something like realmObject.propertyProperty.name
as an alternative?
I'm speaking on my own accord here. Wiser people may have objections to this.
BTW, what about realmObject.properties['property'].name
? Wouldn't that work better for your filter use-case?
We could also generate a type specific schema class. Then something like Fellow.schema.firstName.name
would be possible. Could still allow Fellow.schema.properties['firstName'].name
as well
I put up https://github.com/realm/realm-dart/pull/1078 - it doesn't cover all the requirements of this issue, but it makes it possible to use the model name rather than the mapTo
-name when creating queries (i.e. fellowshipOfTheRing.members.query('firstName == "Hobbit"')
rather than .query(first_name == ...)
I put up https://github.com/realm/realm-dart/pull/1078 - it doesn't cover all the requirements of this issue, but it makes it possible to use the model name rather than the mapTo-name when creating queries (i.e. fellowshipOfTheRing.members.query('firstName == "Hobbit"') rather than .query(first_name == ...)
Brilliant @nirinchev , this makes a ton of sense and will be very helpful. We did think it was odd to use the @MapTo properties in Realm
.query
's. Thank you so much for raising this.
We could also generate a type specific schema class. Then something like Fellow.schema.firstName.name would be possible. Could still allow Fellow.schema.properties['firstName'].name as well
@nielsenko this would be perfect ;-) (both Fellow.schema.firstName.name
and Fellow.schema.properties['firstName'].name
) as we can then build a ListView
in Flutter dynamically, as each Column
(in the ListView
) and its (the Columns
) filters can then be dynamically built:
- Get the
value
(FellowRealmObjectInstance.firstName
) - Get the
type
(Fellow.schema.firstName.type
) so we can then build a range of filters the user (in the Flutter UI) can use (does not contain, contains, etc) - we can use these to dynamically populate theRealm
.query
for the opted for filters. - Get the
name
(Fellow.schema.firstName.name
) to use in theRealm
.query
in point 2 above via #1078
This would open up lots of other use cases around dynamically building widgets based on the type
of the RealmObject
property... i.e. TextFormField
could automatically generated in different ways if it is a String
, int
, etc... Also will be very helpful when streaming RealmResults
from a Realm
.query
, etc...
The above and #1078 certainly removes lots of pain initially and ongoing (maintainability via strict typing i.e. re Realm
schema changes), so would be amazing to have in place. Lots of value.
Great to see https://github.com/realm/realm-dart/pull/1078 merged, thank you all. Will look forward to your further thoughts.