Modeling Sub-Collections in Mongodb Realm Sync

Modeling sub-collections in MongoDB Realm Sync

Your code looks great and your heading the right direction, so this answer is more explanation and suggestions on modeling than hard code.

First, Realm objects are lazily loaded which means they are only loaded when used. Tens of thousands of objects will have very little impact on a devices memory. So suppose you have 10,000 users and you 'load them all in'

let myTenThousandUsers = realm.objects(UserClass.self)

meh, no big deal. However, doing this

let someFilteredUsers = myTenThousandUsers.filter { $0.blah == "blah" }

will (could) create a problem - if that returns 10,000 users they are all loaded into memory possibly overwhelming the device. That's a Swift function and 'converting' Realms lazy data using Swift should generally be avoided (use case dependent)

The observation of this code using Swift .forEach

realm.objects(Project.self).forEach { (project) in
// Access fields
}

could cause issues depending on what's being done with those project objects - using them as a tableView dataSource could be trouble if there are a lot of them.

Second thing is the question about the 16Mb limit per document. For clarity an Atlas document is this

{
field1: value1,
field2: value2,
field3: value3,
...
fieldN: valueN
}

where value can be any of the BSON data types such as other documents, arrays, and arrays of documents.

In your structure, the var tasks = RealmSwift.List<Task>() where Task is an embedded object. While conceptually embedded objects are objects, I believe they count toward a single document limit because they are embedded (correct me if I am wrong); as the number of them grows, the size of the enclosing document grows - keeping in mind that 16Mb of text is an ENORMOUS of text so that would/could equate to millions of tasks per project.

The simple solution is to not embed them and have them stand on their own.

class Task: Object {
@objc dynamic var _id: String = ObjectId.generate().stringValue
@objc dynamic var _partition: String = ""
@objc dynamic var name: String = ""
@objc dynamic var status: String = "Pending"
override static func primaryKey() -> String? {
return "_id"
}
}

Then each one can be 16Mb, and an 'unlimited number' can be associated with a single project. One advantage of embedded objects is a type of cascade delete where when the parent object is deleted, the child objects are as well, but with a 1-many relationship from Project to Tasks - deleting a bunch of tasks belonging to a parent is easy.

Oh - another case for not using embedded objects - especially for this use case - is they cannot have indexed properties. Indexing can greatly speed up some queries.

How do I add MongoDB Realm App Users to Atlas collection?

While I got a lot of useful info from the responses here, the solution I found was not mentioned.

The correct way to do this is still to do a manual copy of data from the Realm to the database via a triggered function.



Related Topics



Leave a reply



Submit