【问题标题】:NSPredicate to detect an entire set of entities being present in multiple entity relationshipsNSPredicate 检测存在于多个实体关系中的一整组实体
【发布时间】:2018-08-03 20:35:17
【问题描述】:

给定这样的核心数据实体设置

  • 实体A
    • aB -> B(多对一)
    • aC -> C(多对1)
    • 儿童 -> 儿童(多对多)
  • 实体B
    • 儿童 -> 儿童(多对多)
  • 实体C
    • 儿童 -> 儿童(多对多)
  • 实体儿童

我正在尝试进行查询以查找所有实体 A,以便在所有可访问的子项中找到一组子实体 TestChildren。类似于此示例的匹配 A 实体 A1

  • TestChildren设置

    • 孩子1
    • 孩子2
    • 孩子3
    • Child4
  • A1实体

    • aB -> B1
    • aC -> C1
    • 儿童
      • -> child1
      • -> child3
  • B1 实体
    • 儿童
      • -> child2
  • C1 实体
    • 儿童
      • -> child4

因此,所有 4 个孩子都已在每个班级的各种孩子关系中找到。

似乎要测试这些集合,我必须对每个 Children 关系执行子查询,但我认为我无法使用 NSPredicate 格式表达我想要的内容。也许它根本无法使用 NSPredicates?

我的一个想法是做这样的事情

  predicateString += "((SUBQUERY(aB.children, $child, $child in %@).@count + SUBQUERY(aC.children, $child, $child in %@).@count + SUBQUERY(children, $child, $child in $@).@count) == $@)"
  predicateVars.append(contentsOf: [testChildren, testChildren, testChildren, testChildren.count])

所有子关系中的匹配总数必须匹配。不幸的是,如果同一个孩子可能出现在多个 A、B 或 C 中,那么这将是不正确的,因为同一个孩子在两个不同的类别将允许总数不正确地匹配。

无论如何,在 NSPredicates 中加起来似乎是不可能的?

真正正确地做到这一点的唯一方法是能够在 3 个类中生成所有子级的总集合,但似乎没有办法在 NSPredicate 中表达这一点?

在更糟糕的情况下,我可以执行更简单的查询并对返回的结果执行更多逻辑,但理想情况下,我会尝试在查询中做尽可能多的繁重工作。

提前致谢

【问题讨论】:

  • 如果所有子关系都是一对多的,那么一个子不能出现在多个 A、B 或 C 中。是否要检查 TestChildren 的所有 A 是否相同一种?还是我误解了这个问题?
  • 你说得对,我把描述弄错了。我现在已经修改了。抱歉.. 它的 A -> B 和 A->C 都是多对一的关系,所有的孩子都是多对多的,你现在可以在原始问题文本中更清楚地看到。
  • 如果有人感兴趣,我在这里添加了另一个使用类似但略有不同的实体层次结构的问题 - stackoverflow.com/questions/51753032/…

标签: core-data nspredicate


【解决方案1】:

谓词查找所有 A 和一个孩子:

NSPredicate(format:"aB.children contains %@ OR aC.children contains %@ OR children contains %@", child, child, child)

AND 谓词查找所有带有child1child2child3child4 的A:

var predicateArray:[NSPredicate] = []
for child in testChildren {
    let predicate = NSPredicate(format:"aB.children contains %@ OR aC.children contains %@ OR children contains %@", child, child, child)
    predicateArray.append(predicate)
}
let finalPredicate = NSCompoundPredicate(andPredicateWithSubpredicates:predicateArray)

【讨论】:

  • 非常感谢您的建议。明天我会尝试一下,如果我能让它工作,我会接受答案!手指交叉!干杯!
  • 这很好用。我最终将它重做为字符串谓词而不是复合谓词,我认为它们是等价的,并且字符串稍后更容易调试,因为您可以阅读整个谓词。我会把我的版本放在另一个答案中,但我已经接受了你的。奇怪的是为什么我们必须单独处理每个孩子,当我阅读 NSPredicate 文档时,看起来你应该能够像我试图做的那样使用实体容器。但无论我尝试什么,我都无法让它发挥作用,因为它工作得很好!
  • 我想知道这些谓词的限制是什么......以字符串形式我确实想知道你可以将它推多远,与复合谓词类似,幸运的是我不希望有超过少数孩子要以这种方式处理.. 它不像会去 10 或 100 多个孩子,这只会是一团糟
【解决方案2】:

上述 Willeke 答案的另一个版本是构建谓词描述为带有变量的字符串,如下所示

var predicateString:String = ""
var predicateVars:[Any] = []

for child in testChildren
{
  if (predicateString.count > 0)
  {
    predicateString += " && "
  }

  predicateString += "(aB.children contains %@ || aC.children contains %@ || children contains %@)"
  predicateVars.append(contentsOf: [child, child, child])
}
let predicate = NSPredicate(format: predicateString, argumentArray: predicateVars)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    相关资源
    最近更新 更多