核心数据子查询语法问题
Core Data SUBQUERY Syntax Issue
我正在尝试使用谓词构建提取请求,该谓词使用子查询遍历核心数据中的某些关系。我的架构如下所示:
我拥有的所有信息都是 ChargeCodeType 和 Employee。我想要做的是获取属于我所拥有的员工的所有 TimeEntries 并总结 TimeEntry 中的小时列。我有一个这种格式的工作子查询:
static func fetchRequestForChargeCodeTypeWithEmployeeNumber(context : NSManagedObjectContext, chargeCodeType : String, employeeId : Int) -> NSFetchRequest{
let entity = NSEntityDescription.entityForName("ChargeCodeType", inManagedObjectContext: context)
let fetchRequest = NSFetchRequest()
fetchRequest.entity = entity
let typePredicate = NSPredicate(format: "type == %@ AND SUBQUERY(chargeCodes, $t, ANY $t.timeEntries.person.employeeID == %@).@count != 0", chargeCodeType, NSNumber(integer:employeeId))
fetchRequest.predicate = typePredicate
return fetchRequest
}
但是我认为这里的问题是 'ANY' 关键字,如果我有多个员工,当我总结收费代码时间条目时,我会为多个用户取回时间条目我总结了收费代码上的时间条目。下面是更相关的代码,展示了我如何使用谓词。
func constructDataSourceYearToDateUtilization(chargeCodeType : String){
let chargeCodeTypeFetchRequest = CoreDataUtilities.fetchRequestForChargeCodeTypeWithEmployeeNumber(coreDataStack.managedObjectContext, chargeCodeType: chargeCodeType, employeeId: employee.employeeID!.integerValue)
chargeCodeTableDataSource = [YTDChargeCodeModel]()
do {
if let chargecodeType = try coreDataStack.managedObjectContext.executeFetchRequest(chargeCodeTypeFetchRequest).first as? ChargeCodeType {
let chargeCodes = chargecodeType.chargeCodes?.allObjects as? [ChargeCode]
yearToDateHoursSum = 0
for chargeCode in chargeCodes! {
let ytdChargeCodeModel = YTDChargeCodeModel()
ytdChargeCodeModel.chargeCode = chargeCode
ytdChargeCodeModel.fullChargeCode = chargeCode.chargeCode
ytdChargeCodeModel.chargeCodeDescription = chargeCode.chargeCodeDescription
ytdChargeCodeModel.totalHours = chargeCode.valueForKeyPath("timeEntries.@sum.hours") as! Int
yearToDateHoursSum = yearToDateHoursSum + ytdChargeCodeModel.totalHours
chargeCodeTableDataSource.append(ytdChargeCodeModel)
}
totalHoursLabel.text = "\(yearToDateHoursSum)hrs"
//Sort by charge code name.
chargeCodeTableDataSource.sortInPlace { [=11=].fullChargeCode!.compare(.fullChargeCode!) == .OrderedAscending }
} else {
print("Could not get the charge code type")
totalHoursLabel.text = "0hrs"
}
} catch let error as NSError {
print("Hit error when fetching user profile with error message: \(error.localizedDescription)")
}
tableView.reloadData()
}
有什么方法可以使它与子查询一起工作,还是我应该重写该方法?
问题不在你的谓词中,而在这一行:
ytdChargeCodeModel.totalHours = chargeCode.valueForKeyPath("timeEntries.@sum.hours") as! Int
@sum
包括相关 chargeCode
的所有 timeEntries
,与员工无关。一个快速的解决方法是遍历所有 timeEntries 并只添加 person.employeeID
匹配的那些(或者等效地将 chargeCode.timeEntries
过滤到临时集,并在其上使用 @sum
)。
您还可以通过使用如下谓词获取 ChargeCode
s 来简化一点:
let typePredicate = NSPredicate(format: "chargeCodeType.type == %@ AND (ANY timeEntries.person.employeeID == %@)", chargeCodeType, NSNumber(integer:employeeId))
而不是获取 ChargeCodeTypes
.
我正在尝试使用谓词构建提取请求,该谓词使用子查询遍历核心数据中的某些关系。我的架构如下所示:
我拥有的所有信息都是 ChargeCodeType 和 Employee。我想要做的是获取属于我所拥有的员工的所有 TimeEntries 并总结 TimeEntry 中的小时列。我有一个这种格式的工作子查询:
static func fetchRequestForChargeCodeTypeWithEmployeeNumber(context : NSManagedObjectContext, chargeCodeType : String, employeeId : Int) -> NSFetchRequest{
let entity = NSEntityDescription.entityForName("ChargeCodeType", inManagedObjectContext: context)
let fetchRequest = NSFetchRequest()
fetchRequest.entity = entity
let typePredicate = NSPredicate(format: "type == %@ AND SUBQUERY(chargeCodes, $t, ANY $t.timeEntries.person.employeeID == %@).@count != 0", chargeCodeType, NSNumber(integer:employeeId))
fetchRequest.predicate = typePredicate
return fetchRequest
}
但是我认为这里的问题是 'ANY' 关键字,如果我有多个员工,当我总结收费代码时间条目时,我会为多个用户取回时间条目我总结了收费代码上的时间条目。下面是更相关的代码,展示了我如何使用谓词。
func constructDataSourceYearToDateUtilization(chargeCodeType : String){
let chargeCodeTypeFetchRequest = CoreDataUtilities.fetchRequestForChargeCodeTypeWithEmployeeNumber(coreDataStack.managedObjectContext, chargeCodeType: chargeCodeType, employeeId: employee.employeeID!.integerValue)
chargeCodeTableDataSource = [YTDChargeCodeModel]()
do {
if let chargecodeType = try coreDataStack.managedObjectContext.executeFetchRequest(chargeCodeTypeFetchRequest).first as? ChargeCodeType {
let chargeCodes = chargecodeType.chargeCodes?.allObjects as? [ChargeCode]
yearToDateHoursSum = 0
for chargeCode in chargeCodes! {
let ytdChargeCodeModel = YTDChargeCodeModel()
ytdChargeCodeModel.chargeCode = chargeCode
ytdChargeCodeModel.fullChargeCode = chargeCode.chargeCode
ytdChargeCodeModel.chargeCodeDescription = chargeCode.chargeCodeDescription
ytdChargeCodeModel.totalHours = chargeCode.valueForKeyPath("timeEntries.@sum.hours") as! Int
yearToDateHoursSum = yearToDateHoursSum + ytdChargeCodeModel.totalHours
chargeCodeTableDataSource.append(ytdChargeCodeModel)
}
totalHoursLabel.text = "\(yearToDateHoursSum)hrs"
//Sort by charge code name.
chargeCodeTableDataSource.sortInPlace { [=11=].fullChargeCode!.compare(.fullChargeCode!) == .OrderedAscending }
} else {
print("Could not get the charge code type")
totalHoursLabel.text = "0hrs"
}
} catch let error as NSError {
print("Hit error when fetching user profile with error message: \(error.localizedDescription)")
}
tableView.reloadData()
}
有什么方法可以使它与子查询一起工作,还是我应该重写该方法?
问题不在你的谓词中,而在这一行:
ytdChargeCodeModel.totalHours = chargeCode.valueForKeyPath("timeEntries.@sum.hours") as! Int
@sum
包括相关 chargeCode
的所有 timeEntries
,与员工无关。一个快速的解决方法是遍历所有 timeEntries 并只添加 person.employeeID
匹配的那些(或者等效地将 chargeCode.timeEntries
过滤到临时集,并在其上使用 @sum
)。
您还可以通过使用如下谓词获取 ChargeCode
s 来简化一点:
let typePredicate = NSPredicate(format: "chargeCodeType.type == %@ AND (ANY timeEntries.person.employeeID == %@)", chargeCodeType, NSNumber(integer:employeeId))
而不是获取 ChargeCodeTypes
.