Realms as documents?

(Lester Ward) #1

I’d like to build an application to support multiple documents (subclassing NSDocument), where each document is a different realm database. Has anyone set up such a thing or know where I might find an example of doing so on line?

(jay) #2

That seems like a bit unusual. Can you elaborate on your use case? Why does each document need to be a totally separate database? It shouldn’t be too much of a challenge to map NSDocument data to a separate database but what kind of objects will you be storing in each database and why do they need to be separated in that fashion?

(Lester Ward) #3

Same reason documents are used all the time:

  • A document isolates its data domain from others, making a self-contained data set.
  • Documents can be transferred around.
  • Apps can open documents, do work, close them, open other documents.

(Zsolt Jandzso) #4

Do you know, that you can use multiple realm files in a same app, right?
No need to use documents.

(jay) #5

What a document is, was not the question, and how you deal with the Realm data within your app once it’s read in is up to you. You can store data in Realm Results or in classes or structs, in an array of dictionaries or stuff it into an NSDocument. Realm however is not a document store so you will need to read your Realm data and put it into whatever format is appropriate for your app. What you stated was

each document is a different realm database.

And I was asking why each one would need a separate Realm? That kinda defeats the purpose of storing the same object types in a database. If you have 1000 different inventory items, why store them in 1000 different Realm databases? That can become high inefficient, unnecessarily redundant and make queries that should be simple, very complex. Why not store similar objects in one database, read them as needed and if you like put each set of data into a NSDocument in your app.

I was asking for a use case. For example, I am a wine collector and have an app to organize my wines (about 1000 of them). Each has a vineyard, a vintage, a rating and red or white (no rose` for me!)

I could store each wine in a separate Realm database and when I wanted to know more about the wine, I could read the data from Realm and ‘put it’ in an NSDocument.

But what if I wanted all red wines? If I have each wine stored as a different Realm database, I would have to go through every one to see if it’s red and if so, load it in. However, if I have all the wines stored in one database, I can run one query and get ALL red wines.

Maybe you’re asking something else, so perhaps some more clarity in the question would help us better understand your use case.

(Lester Ward) #6

Not what I’m asking at all. Use case, from the point of view of the end user:

Alice and Bob are both project managers. Alice uses my app to track two projects. Each project is saved in its own document, because they are for different clients and will never interact at all. Alice would like to open both documents at once, so she can see them together, but the two projects don’t interact. The projects, however, do follow the same schema. Each has a timeline, list of tasks, contact information and so on (all stored as records).

Alice has project A and project B, managed as two documents, with New, Open, Save, Save As, and similar functionality. Alice gets a assigned a new project, and has to hand Project A over to Bob.

She hands Bob the document representing project B (and all of the records in contains). Bob uses my app, picks File -> Open and opens the document containing project B.

(jay) #7

Right. Got it. Allow me to provide an example that may help clarify.

I am sure you know this but for clarity, Realm is a relational database that stores data in different ‘tables’ of related information. Each row in a table represents one discreet set of data, like a document. Realm provides relational calls to relate objects in one table to another.

For your example, there’s would be a ‘projects’ table. Each ‘row’ in the table represents one project. There are other tables of associated data as well. For example your projects table has the following schema

class ProjectClass: Object {
   @objc dynamic var manager: UserClass
   @objc dynamic var start_date: Date
    let milestoneList = List<MilestoneClass>()

then your Milestones table has the following schema

class MilestoneClass: Object {
   @objc dynamic var title = ""
   @objc dynamic var description = ""
   @objc dynamic var date: Date
   @objc dynamic var linkedToProject: ProjectClass

As you can see, each project is discreet and nicely organized in a projects table. Each project has associated milestones (milestoneList property) that are stored in the milestones table. The projects have a List of milestones and the milestones know which project they belong to.

Then… take a look at the ProjectClass manager, which is a UserClass

class UserClass: Object {
   @objc dynamic var name = ""
   @objc dynamic var projectList = List<ProjectClass>

Suppose Bob wants to get a list of ALL of his projects. If they were stored in separate Realms, you would literally have to poll every one to see if Bob is the manager. When they are stored together as in this example, it’s a snap

let bobsProjects = realm.objects(ProjectClass.self).filter("manager = %@", bobUser)

and now Bob has a list of all of his projects and when clicking on one project can see all of the milestones for that project.

This gets ever cooler because if your milestones have resources, like people, to handle them, when all of the milestones are stored in one table, you can ensure that Person A is not assigned to two milestones at the same time. That may not be the case, but as you can see there’s no reason to store every project in its own Realm.

This structure allows a user to open multiple projects and related data simultaneously, work with the data within the project (New Open Save etc) And if you need to assign it to another user, just update the manager property.

Also, for maintainability, suppose you want to add a location property to your projects. If there’s a 1000 different projects (Realms) every one would have to be modified. Using Realm like I describe, add it once and it’s done!

If you’ve not done so, go through the Getting Started Guide - it uses a Person & Dogs example that highlights the relational aspect of Realm and how to implement it.

(Lester Ward) #8

Wow. Just… no. Your lengthy response can be summarized as you saying “your use case is wrong, do it my way instead”. Yes, what you describe is the classical way you’d build an application using Realm, with a monolithic database backing everything. Doing that is not confusing, and much example code exists indicating how to do so.

There do not appear to be many (any?) examples doing what I am actually asking about, which is using macOS’s document model, using Realm for the persistence of those documents (instead of, say, Core Data, SQLllite, etc.). I get that you would not build your app that way. I want to.

One statement in your reply is particularly wrong: “Each row in a table represents one discreet set of data, like a document”. No, a record in the project table is not “like a document”. It’s a record in table. In the use case I actually specified, the document would contain all the tables needed for that one project (so, yes, there would be a single record in that project table, but hundreds or thousands of other records in other tables, containing the totality of the project). Again, yes, I get that you wouldn’t build it that way. (Presumably, for the part of my use case where Alice hands a project over to Bob, you’d handle it with some sort of export/import workflow.)

Should I just assume by the responses here that Realm either can’t or won’t do this? Granted, it is not the primary mode of operation, but I’d assume someone has done it somewhere. It seemed possible, but I couldn’t quite figure out where in the NSDocument was the best place to add overrides and what those overrides would look like. I assumed someone/somewhere has shared how to do this. Should I use some other, more capable, database?

(Lester Ward) #9

Great. Can you point me to some sample code that does this?

(jay) #10

Wow. Just… no. Your lengthy response can be summarized as you saying “your use case is wrong, do it my way instead”.

You appear to have overlooked us trying to help you. Did you miss this part?

Allow me to provide an example that may help clarify.

I was simply presenting my use case that may or may not work for your situation.

One statement in your reply is particularly wrong: “Each row in a table represents one discreet set of data, like a document”. No, a record in the project table is not “like a document”.

Not sure how that’s particularly wrong as I can certainly store a document, an image, a string, an integer in Realm. Realm fully supports NSData so you can pretty much store anything, as long as it’s size is within the Realm limits.

The presented use case is very general and my solution would work based on what was stated. If you don’t like it that’s totally cool - just trying to help. After coding for going on 40 years, I find that being open to other ideas (even if I don’t like them!) makes me a better coder, but asking questions is the key - which is why I was asking for your use case.

Can you store an NSDocument in Realm? Yes, if that’s what you are asking.

Oh - using multiple Realm files is somewhat covered in the docs but it will depend on if you are using a local realm or query based or fully synced as the set up is a bit different.

Here’s the Use Multiple Realms link

(Zsolt Jandzso) #11

Please read the documentation first, so you will get the basic idea behind a toolset.
Do that before you actually want to use it for a certain application.

I am refusing to help you anymore.

(Lester Ward) #12

Google is suddenly being more useful than it was a month ago. This is the answer to my question: NSDocument with Realm persistence