简体   繁体   中英

Filtering many-to-many relation by comparing objects agains keypath of objects in array with NSPredicate in swift

I hope you can help me. I'm building a Mac OS X App using Realm as the underlaying database system.

My model looks like this:

-Brick: a text brick consisting of the properties title and text

-GeneratorBrick: a many-to-many relation object for modeling the relation between Generator, Brick and some other data which is not relevant to the problem. Property on this object is called "brick"

-Generator: a configuration consisting of some text as well as a list of GeneratorBricks whose property name is "generatorBricks"

In my App, I now have a Generator object. This one holds a list to a bunch of GeneratorBrick objects which themselves each have a Brick and some other data. I display them in a TableView. I now want to display another TableView in which I only show those Brick objects which are not in the TableView of the current Generator. Bricks in the generator i access by generator.generatorBricks[index].brick

In an earlier version of my App I loaded all the Brick objects I needed via var bricks: Results<Brick> = try! Realm().objects(Brick).sorted("title").filter("inGenerator = false") var bricks: Results<Brick> = try! Realm().objects(Brick).sorted("title").filter("inGenerator = false") but since my model changed from using a property "inGenerator" to using another model class "GeneratorBrick" I need another way to filter. Unfortunately I have no idea how to accomplish this task. I tried different predicates like generatorBricks IN %@", generator.generatorBricks where the property "generatorBricks" is a backlink property in the Brick class.

Maybe I'm trying something which cannot be accomplished by using a predicate or maybe I just have not enough experience with predicates. Maybe I'm blind because I'm more used to plain SQL where I would use something like the following:

create table brick (
  id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  title varchar(255)
);
create table generator (
  id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  title varchar(255)
);

create table generatorbrick (
  id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  brickId INT(6),
  generatorId INT(6)
) 

select * from brick b join generatorbrick gb on b.id = gb.brickid where gb.generatorid is not 123

Do you understandy my problem? Do you need additional information? I'm glad to provide if you can give me a hint into the right direction. Thank you in advance.

What you would do in traditional SQL with (expensive) join operations, you should do in Realm with (cheap) graph relationships:

class Brick: Object {
  dynamic var title = ""
}
class BrickGenerator: Object {
  dynamic var id = 0
  dynamic var title = ""
  dynamic var brick: Brick? = nil
}

let realm = try! Realm()
let brick = realm.objects(BrickGenerator).filter("id != 123").first?.brick

I'm not 100% sure if this is the operation you're attempting to model, and I'm under the impression that these models could be simplified even more if I truly understood what you were trying to accomplish.

But the gist is that Realm is a graph database (not relational), so links are represented natively. Try to think of what your models would look like if they were 100% in-memory, plain old Swift objects (classes/structs).

I came to the conclusion that what I want to do is not simply achievable with graph based Realm. At least not without loading all the bricks, generatorbricks and the generator and do a manually comparison by iterating over all the bricks and check if they are part of the current generator.

I would have needed something like

SELECT brick.* FROM brick JOIN generatorbrick on brick.id = generatorbrick.brickId JOIN generator on generator.id = generatorbrick.generatorId WHERE generator.id != 123

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM