How to write MongoDB Realm Schema? - ios

I'm trying to enable Sync with MongoDB Realm on my iOS app. The app already uses Realm DB, but I'm having trouble creating the schemas for my classes due to some less primitive variables. How would you write the following classes as schema (I'm mostly having trouble with List<Assignment> and the LinkingObjects variables)?
class Course: Object{
#objc dynamic var _id: ObjectId = ObjectId.generate()
#objc dynamic var _partitionKey: String = ""
#objc dynamic var name: String = ""
var days = List<String>()
let assignments = List<Assignment>()
}
class Assignment: Object{
#objc dynamic var _id: ObjectId = ObjectId.generate()
#objc dynamic var _partitionKey: String = ""
#objc dynamic var name: String = ""
var parentCourse = LinkingObjects(fromType: Course.self, property: "assignments")
}

With Realm, you don't need to 'write schemas' - it's done for you based on the properties of your classes.
For example, when an Realm object is defined in your app, when the app first Sync's to MongoDB Realm Cloud the objects schema is auto-generated. So for example let say I have an app that tracks people and their dogs. If I create the following Object in my app
class Person: Object {
#objc dynamic var _id = ObjectId.generate()
#objc dynamic var _partitionKey = ""
#objc dynamic var name = ""
}
and run the app, as soon as the app 'speaks' to MongoDB Realm, an object will be created on the server and in your local file with schema based on those Person properties. Nothing more is required or even needed
On the topic of primitives, Realm Collections do not support primitives (very well).
EDIT: Release 10.7 added support for filters/queries as well as aggregate functions on primitives so the below info is no longer completely valid. However, it's still something to be aware of.
So they should be avoided. If you want to store objects in Lists, create a Realm object with the primitive as the property.
In your question you have
var days = List<String>()
this should be changed to
class DayClass: Object {
#objc dynamic var date = ""
}
let days = List<DayClass>()
Realm does not support queries on a List of primitives and also doesn't support aggregative function on primitives (yet)
What that means is by storing another object within the List, you can use functions like .sum, .min, .max, .count etc. on those objects.
You code is very close and LinkingObjects are perfect. So just a slight change for the List and everything should work as is.

Related

Realm #count query issue

I have tried to use the #count function to get data according to that but it somehow crashed without crash report.
Here is the code
class PSMedia: Object {
#objc dynamic var id = ""
#objc dynamic var promotional_status = false
var promotions = List<String>()
}
And here is that query that caused an issue
realm.objects(PSMedia.self).filter("promotions.#count <= 5")
What's wrong here? I have followed realm swift doc and used the #count function same as described in that doc.
I am pretty sure #count does not work on Lists of primitives. Realm didn't used to support lists of primitives at all, it now does but there is some missing functionality.
EDIT: Release 10.7 added support for filters/queries as well as aggregate functions on primitives so the below info is no longer completely valid. However, it's still something to be aware of.
Change your promotions to be a list of other realm objects
class PromotionClass: Object {
#objc dynamic var promotion = ""
}
and then
class PSMedia: Object {
#objc dynamic var id = ""
#objc dynamic var promotional_status = false
let promotions = List<PromotionClass>()
}
then this will work
realm.objects(PSMedia.self).filter("promotions.#count <= 5")
EDIT
Yep, that's correct. It's not supported. Here's the Github link for that issue
Swift docs should make it clear that filtering by someListOfPrimitives.#count isn't supported #6079

How to compare two lists of String in Realm Swift?

I have the following Realm data structure:
class Pair {
#objc dynamic var kanji: String? = nil
let kana = List<String>()
}
I need to look up an entry in the Realm the Pair.kana property of which has the same elements. How do I achieve that (preferably using NSPredicate)?

Retrieving object properties with relation to their parent categories

I am new to realm and iOS development so I apologize in advance if something isn’t explained properly or is just incorrect.
I have 2 Realm Object classes:
class Category: Object {
#objc dynamic var name: String = ""
#objc dynamic var color: String = ""
let trackers = List<Tracker>()
}
and
class Tracker: Object {
#objc dynamic var timeSegment: Int = 0
var parentCategory = LinkingObjects(fromType: Category.self, property:
"trackers")
}
I’m able to store new timeSegment properties consistently; however, the issue is that I cannot retrieve & display a collection of timeSegment values relating to their parentCategory. setting
var entries : Results<Tracker>?
produces all results for every category, which is the only result i'm able to pull so far after testing.
Any help is appreciated, and can follow up with any additional details. Thanks
You need to call objects on your Realm object with a filter for fetching only results that match a predicate. The realm object in this code is an instance of the Realm class.
func getTrackersWithName(_ name: String) -> Results<Tracker> {
return realm.objects(Tracker.self).filter("name = \"\(name)\"")
}
This tells Realm to fetch all objects that match the filter predicate. In this case, the filter predicate matches any object where the value of the "name" property matches the string that is passed into the method.

Computed properties using Realm LinkedObject instances return nil

I'm experiencing slightly unusual behaviour when attempting to use computed properties to access linked Objects in a Realm Object subclass.
final class Patient: Object {
dynamic var name: String = ""
var parameters = List<Parameter>()
}
final class Parameter: Object {
dynamic var name: String = ""
dynamic var patient: Patient? {
return LinkingObjects(fromType: Patient.self, property: "parameters").first
}
}
The patient property on the Parameter class returns nil but, if you replace the code with the following, we get the expected behaviour:
var p = LinkingObjects(fromType: Patient.self, property: "parameters")
var q: Patient? {
return p.first
}
I suspect this is something to do with Realm's internal representation of LinkingObject. The code I used originally was referenced in a previous StackOverflow question and was accepted as a functional solution thus I guess it worked then so perhaps something has changed? Xcode 7, Swift 2.2
When Realm added the ability to query inverse relationships, that became the syntax to specify them. See https://realm.io/news/realm-objc-swift-0.100.0/ and https://realm.io/docs/swift/latest/#inverse-relationships for details.

Realm iOS relationship from mysql json results

I want to use Realm to my iOS app but I have a problem with the relationship. What I want to achieve is a relationship between the following two RLMobjects :
class Catalogue: RLMObject {
dynamic var ID = ""
dynamic var greekName = ""
dynamic var deutschName = ""
dynamic var createdAt = NSDate()
dynamic var updatedAt = NSDate()
override class func primaryKey() -> String? {
return "ID"
}
}
class Products: RLMObject {
dynamic var foodName = ""
dynamic var foodDescription = ""
dynamic var foodPrice = ""
dynamic var createdAt = NSDate()
dynamic var updatedAt = NSDate()
dynamic var category: Catalogue?
}
I am retrieving all my data from a server in JSON format and the problem is that
I can not set the category as relationship to Catalogue ID.
In my database the category field is a foreign key to the Catalogue ID.
Does anyone knows how can I do that in Realm?
Thank you in advance.
Rather than storing the Catalogue ID in the dynamic var category: Catalogue? relationship field you will need to find the Catalogue object and just store that directly. This is how you link objects and is an important and powerful part of using NoSQL type DB's like Realm.
I would also add an array of products relationship on Catalogue so that you can link all the products to the Catalogue itself.
You can see more discussion about this here if that wasn't fully clear. Hope this helps

Resources