MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Modellieren von Untersammlungen in MongoDB Realm Sync

Ihr Code sieht gut aus und Sie gehen in die richtige Richtung, daher enthält diese Antwort mehr Erklärungen und Vorschläge zur Modellierung als harten Code.

Erstens sind Realm-Objekte faul geladen Das heißt, sie werden nur geladen, wenn sie verwendet werden. Zehntausende von Objekten haben nur sehr geringe Auswirkungen auf den Speicher eines Geräts. Angenommen, Sie haben 10.000 Benutzer und laden sie alle ein

let myTenThousandUsers = realm.objects(UserClass.self)

mh, keine große sache. Allerdings tun dies

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

wird (könnte) ein Problem verursachen - wenn das 10.000 Benutzer zurückgibt werden sie alle in den Speicher geladen möglicherweise das Gerät überfordert. Das ist eine Swift-Funktion und das 'Konvertieren' fauler Realms-Daten mit Swift sollte im Allgemeinen vermieden werden (je nach Anwendungsfall)

Die Beobachtung dieses Codes mit Swift .forEach

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

kann Probleme verursachen, je nachdem, was mit diesen Projektobjekten gemacht wird - ihre Verwendung als TableView-Datenquelle könnte Probleme bereiten, wenn es viele davon gibt.

Zweitens ist die Frage nach der 16-MB-Grenze pro Dokument. Zur Verdeutlichung ist dies ein Atlas-Dokument

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

wobei value jeder der BSON-Datentypen sein kann, wie andere Dokumente, Arrays und Arrays von Dokumenten.

In Ihrer Struktur ist die var tasks = RealmSwift.List<Task>() wobei Task ein eingebettetes Objekt ist . Während konzeptionell eingebettete Objekte Objekte sind, glaube ich, dass sie zu einer Begrenzung auf ein einzelnes Dokument zählen, weil sie eingebettet sind (korrigieren Sie mich, wenn ich falsch liege); Mit zunehmender Anzahl wächst auch die Größe des beigefügten Dokuments - wenn man bedenkt, dass 16 MB Text eine ENORME Textmenge sind, die Millionen von Aufgaben pro Projekt entsprechen würde/könnte.

Die einfache Lösung besteht darin, sie nicht einzubetten und sie für sich allein stehen zu lassen.

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"
    }
}

Dann kann jede 16 MB groß sein, und eine „unbegrenzte Anzahl“ kann einem einzelnen Projekt zugeordnet werden. Ein Vorteil von eingebetteten Objekten ist eine Art Kaskadenlöschung, bei der beim Löschen des übergeordneten Objekts auch die untergeordneten Objekte gelöscht werden, aber mit einer 1-viele-Beziehung von Projekt zu Aufgaben - das Löschen einer Reihe von Aufgaben, die zu einem übergeordneten Objekt gehören, ist einfach.

Oh – ein weiteres Argument dafür, eingebettete Objekte nicht zu verwenden – insbesondere für diesen Anwendungsfall – ist, dass sie keine indizierten Eigenschaften haben können. Indizierung kann einige Abfragen erheblich beschleunigen.