通过在 swift 中使用 NSPredicate 比较对象与数组中对象的键路径来过滤多对多关系

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

希望你能帮助我。我正在构建一个 Mac OS X 应用程序,使用 Realm 作为底层数据库系统。

我的模型是这样的:

-Brick:由属性 title 和 text 组成的文本 brick

-GeneratorBrick:多对多关系对象,用于建模Generator、Brick和其他一些与问题无关的数据之间的关系。 属性 在这个对象上被称为 "brick"

-Generator:由一些文本和 属性 名称为 "generatorBricks"

的 GeneratorBricks 列表组成的配置

在我的应用程序中,我现在有一个生成器对象。这个包含一组 GeneratorBrick 对象的列表,每个对象本身都有一个 Brick 和一些其他数据。我将它们显示在 TableView 中。我现在想显示另一个 TableView,其中我只显示那些不在当前生成器的 TableView 中的 Brick 对象。我访问的发电机中的砖块 generator.generatorBricks[index].brick

在我的应用程序的早期版本中,我通过 var bricks: Results<Brick> = try! Realm().objects(Brick).sorted("title").filter("inGenerator = false") 加载了我需要的所有 Brick 对象,但是由于我的模型从使用 属性 "inGenerator" 更改为使用另一个模型 class "GeneratorBrick" 我需要另一种过滤方式。不幸的是,我不知道如何完成这项任务。我尝试了不同的谓词,例如 generatorBricks IN %@", generator.generatorBricks,其中 属性 "generatorBricks" 是 Brick class.

中的反向链接 属性

也许我正在尝试使用谓词无法完成的事情,或者我可能只是没有足够的谓词经验。也许我是盲人,因为我更习惯于在 SQL 中使用类似以下内容的地方:

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

你明白我的问题了吗?您需要更多信息吗?如果您能给我一个正确方向的提示,我很乐意提供。提前谢谢你。

您在传统 SQL 中使用(昂贵的)连接操作所做的事情,您应该在 Realm 中使用(廉价的)图形关系进行:

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

我不能 100% 确定这是否是您尝试建模的操作,而且我的印象是,如果我真正了解您要完成的任务,这些模型可以进一步简化。

但要点是 Realm 是一个图形数据库(非关系型),因此链接是本地表示的。试着想想如果你的模型是 100% 在内存中的,普通的旧 Swift 对象 (classes/structs)。

我得出的结论是,我想做的事情并不能简单地通过基于图形的 Realm 来实现。至少在不加载所有砖块、generatorbricks 和发电机的情况下,并通过遍历所有砖块并检查它们是否是当前发电机的一部分来进行手动比较。

我需要像

这样的东西

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