如何添加 "one-to-many" 的 "one-to" 部分以获取结果
How to add "one-to" part of "one-to-many" to fetch results
我希望能够将玩家的数据添加到许多关系的 "to-one" 部分。 fetch 为我做了一些聚合,但我想知道它属于什么player
。
我有一个如下所示的 CoreData 模型:
我有一个如下所示的提取请求:
func statsPerPlayer(player: Players, managedContext: NSManagedObjectContext) -> [String: Int] {
var resultsDic = [String: Int]()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Shifts")
let predicate = NSPredicate(format: "playersRelationship = %@", player)
fetchRequest.predicate = predicate
let nsExpressionForKeyPath = NSExpression(forKeyPath: "timeOnIce")
let nsExpressionForFunctionMin = NSExpression(forFunction: "min:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionMin = NSExpressionDescription()
nsExpressionDescriptionMin.expression = nsExpressionForFunctionMin
nsExpressionDescriptionMin.name = "minShift"
nsExpressionDescriptionMin.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionMax = NSExpression(forFunction: "max:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionMax = NSExpressionDescription()
nsExpressionDescriptionMax.expression = nsExpressionForFunctionMax
nsExpressionDescriptionMax.name = "maxShift"
nsExpressionDescriptionMax.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionSum = NSExpression(forFunction: "sum:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionSum = NSExpressionDescription()
nsExpressionDescriptionSum.expression = nsExpressionForFunctionSum
nsExpressionDescriptionSum.name = "sumShift"
nsExpressionDescriptionSum.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionAvg = NSExpression(forFunction: "average:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionAvg = NSExpressionDescription()
nsExpressionDescriptionAvg.expression = nsExpressionForFunctionAvg
nsExpressionDescriptionAvg.name = "avgShift"
nsExpressionDescriptionAvg.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionCount = NSExpression(forFunction: "count:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionCount = NSExpressionDescription()
nsExpressionDescriptionCount.expression = nsExpressionForFunctionCount
nsExpressionDescriptionCount.name = "countShift"
nsExpressionDescriptionCount.expressionResultType = .integer16AttributeType
fetchRequest.propertiesToFetch = [nsExpressionDescriptionMin, nsExpressionDescriptionMax, nsExpressionDescriptionSum, nsExpressionDescriptionAvg, nsExpressionDescriptionCount]
fetchRequest.resultType = .dictionaryResultType
do {
let fetchArray = try managedContext.fetch(fetchRequest)
print(fetchArray)
resultsDic = fetchArray.first as! [String : Int]
} catch let error as NSError {
print("\(self) -> \(#function): Could not fetch. \(error), \(error.userInfo)")
}
return resultsDic
} //statsPerPlayer
结果看起来不错,像这样:
[{
avgShift = 39;
countShift = 4;
maxShift = 89;
minShift = 6;
sumShift = 157;
}]
但是,我想包括此数据所针对的 player
。如何在结果中添加 one-to-many
关系的 "to-one"
部分?
谢谢!!
在您上面的代码中,只需将相关关系名称添加到要获取的属性即可:
fetchRequest.propertiesToFetch = ["playersRelationship", nsExpressionDescriptionMin, nsExpressionDescriptionMax, nsExpressionDescriptionSum, nsExpressionDescriptionAvg, nsExpressionDescriptionCount]
返回的字典将包含键 "playersRelationship",其值设置为相应 Players
对象的 NSManagedObjectID
。然后,您可以使用上下文的 object(with:)
方法访问 Players
对象本身。
更新
所以经过一些测试,结果是:
a) 如果在 propertiesToFetch 中包含关系,CoreData 会对 count
聚合函数感到困惑。这会导致 Invalid keypath (request for aggregate operation on a toOne-only keypath
错误。
b) 如果将关系包含在 propertiesToFetch 中,CoreData 会混淆所有其他聚合函数。 (它计算每个对象的聚合,而不仅仅是那些匹配谓词的对象。)
这两个问题的解决方案是将关系添加为 GROUP BY 属性。然后 CoreData 正确地计算聚合并且也正确地将 count
识别为有效操作。因此,添加以下行:
fetchRequest.propertiesToGroupBy = ["playersRelationship"]
我希望能够将玩家的数据添加到许多关系的 "to-one" 部分。 fetch 为我做了一些聚合,但我想知道它属于什么player
。
我有一个如下所示的 CoreData 模型:
我有一个如下所示的提取请求:
func statsPerPlayer(player: Players, managedContext: NSManagedObjectContext) -> [String: Int] {
var resultsDic = [String: Int]()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Shifts")
let predicate = NSPredicate(format: "playersRelationship = %@", player)
fetchRequest.predicate = predicate
let nsExpressionForKeyPath = NSExpression(forKeyPath: "timeOnIce")
let nsExpressionForFunctionMin = NSExpression(forFunction: "min:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionMin = NSExpressionDescription()
nsExpressionDescriptionMin.expression = nsExpressionForFunctionMin
nsExpressionDescriptionMin.name = "minShift"
nsExpressionDescriptionMin.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionMax = NSExpression(forFunction: "max:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionMax = NSExpressionDescription()
nsExpressionDescriptionMax.expression = nsExpressionForFunctionMax
nsExpressionDescriptionMax.name = "maxShift"
nsExpressionDescriptionMax.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionSum = NSExpression(forFunction: "sum:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionSum = NSExpressionDescription()
nsExpressionDescriptionSum.expression = nsExpressionForFunctionSum
nsExpressionDescriptionSum.name = "sumShift"
nsExpressionDescriptionSum.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionAvg = NSExpression(forFunction: "average:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionAvg = NSExpressionDescription()
nsExpressionDescriptionAvg.expression = nsExpressionForFunctionAvg
nsExpressionDescriptionAvg.name = "avgShift"
nsExpressionDescriptionAvg.expressionResultType = .integer16AttributeType
let nsExpressionForFunctionCount = NSExpression(forFunction: "count:", arguments: [nsExpressionForKeyPath])
let nsExpressionDescriptionCount = NSExpressionDescription()
nsExpressionDescriptionCount.expression = nsExpressionForFunctionCount
nsExpressionDescriptionCount.name = "countShift"
nsExpressionDescriptionCount.expressionResultType = .integer16AttributeType
fetchRequest.propertiesToFetch = [nsExpressionDescriptionMin, nsExpressionDescriptionMax, nsExpressionDescriptionSum, nsExpressionDescriptionAvg, nsExpressionDescriptionCount]
fetchRequest.resultType = .dictionaryResultType
do {
let fetchArray = try managedContext.fetch(fetchRequest)
print(fetchArray)
resultsDic = fetchArray.first as! [String : Int]
} catch let error as NSError {
print("\(self) -> \(#function): Could not fetch. \(error), \(error.userInfo)")
}
return resultsDic
} //statsPerPlayer
结果看起来不错,像这样:
[{
avgShift = 39;
countShift = 4;
maxShift = 89;
minShift = 6;
sumShift = 157;
}]
但是,我想包括此数据所针对的 player
。如何在结果中添加 one-to-many
关系的 "to-one"
部分?
谢谢!!
在您上面的代码中,只需将相关关系名称添加到要获取的属性即可:
fetchRequest.propertiesToFetch = ["playersRelationship", nsExpressionDescriptionMin, nsExpressionDescriptionMax, nsExpressionDescriptionSum, nsExpressionDescriptionAvg, nsExpressionDescriptionCount]
返回的字典将包含键 "playersRelationship",其值设置为相应 Players
对象的 NSManagedObjectID
。然后,您可以使用上下文的 object(with:)
方法访问 Players
对象本身。
更新
所以经过一些测试,结果是:
a) 如果在 propertiesToFetch 中包含关系,CoreData 会对 count
聚合函数感到困惑。这会导致 Invalid keypath (request for aggregate operation on a toOne-only keypath
错误。
b) 如果将关系包含在 propertiesToFetch 中,CoreData 会混淆所有其他聚合函数。 (它计算每个对象的聚合,而不仅仅是那些匹配谓词的对象。)
这两个问题的解决方案是将关系添加为 GROUP BY 属性。然后 CoreData 正确地计算聚合并且也正确地将 count
识别为有效操作。因此,添加以下行:
fetchRequest.propertiesToGroupBy = ["playersRelationship"]