I'm stuck with this problem for a while now I can't seem to think of a way to get it right. I'll try to explain it as clear as I can.
There are 3 entities in my core data model. Workplace, Patient and Handover.
A Workplace can have multiple Patients. Also a Patient can belong to multiple Workplaces.
A Patient can have one Handover and vice versa.
In the app, a list of Workplaces are shown to the user. When the user selects a Workplace, I need to get a set Patients who belong to that selected Workplace and have Handovers for today. Since a Patient can have multiple Handovers, there can be duplicate records for Patients and that's okay.
This is what I'm doing now. First I retrieve the Workplace object for the user selected. Then I iterate through it's Patients and extract the IDs of Patient objects and collect them in to an array. Then I pass the array of patient IDs and the date to filter out the Patients who have Handovers for the given date.
let workplace = db.loadWorkplace(155) // 155 is the ID of the Workplace
var patientIDs: [Int] = []
for p in workplace.patients {
let patient = p as Patient
patientIDs.append(patient.id)
}
handovers = db.loadHandovers(patientIDs, date: NSDate.date())
This is the method that des the filtering.
public func loadHandovers(patients: [Int], date: NSDate) -> [AnyObject] {
let fetchRequest = NSFetchRequest()
let entityDescription = NSEntityDescription.entityForName("Handover", inManagedObjectContext: managedObjectContext!)
let patientPredicate = NSPredicate(format: "patient.id IN %@", patients)
let datePredicate = NSPredicate(format: "date > %@ AND date < %@", getStartDate(date), getEndDate(date))
let compoundPredicate = NSCompoundPredicate(type: .AndPredicateType, subpredicates: [patientPredicate, datePredicate])
fetchRequest.entity = entityDescription
fetchRequest.predicate = compoundPredicate
var error: NSError?
let result = managedObjectContext?.executeFetchRequest(fetchRequest, error: &error)
return result!
}
The getStartDate()
and getEndDate()
methods convert the NSDate
object and get its start time and end time to get a date frame. I have them used in some other places and they work. Here's a detailed explanation about it.
Anyway my loadHandovers()
method returns 0 results. It cannot be because when I insert data, I can see Handovers for today. Below is the SQL query that is executed from core data.
SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZDATE, t0.ZSIGNEDBY, t0.ZSTATUS, t0.ZPATIENT
FROM ZHANDOVER t0
JOIN ZPATIENT t1 ON t0.ZPATIENT = t1.Z_PK
WHERE ( t1.ZID IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
AND ( t0.ZDATE > ? AND t0.ZDATE < ?))
Can anyone please tell me if its something wrong with my predicates? Or if there are different ways to approach this altogether? I'd really appreciate it.
Thank you.
Using the object graph, this seems really simple. Try to avoid the verbose fetch requests.
workplace.patients.filteredSetUsingPredicate(
NSPredicate(format: "handovers.date > %@ && handovers.date < %@",
startOfDay, endOfDay))
You seem a bit confused about your own setup. If a patient only has one Handover
, why call the relationship handovers
in the plural?
Another flaw with your setup is illustrated by the contradictory statement
"Since a Patient can have multiple Handovers..."
In your data model, a patient can have one handover, not many. The only explanation is that you are maintaining multiple Patient
instances for the same patient, just because the patient has more than one handover. That is certainly illogical and a partial reason for your confusion and the error you encounter.
A better data structure, avoiding duplicate patients:
Workplace <<---->> Patient <---->> Handover
This assumes that the handovers have nothing to do with the hospital. If they do, you should use the Handover
entity as a kind of join table as suggested by @DanK:
Workplace <---->> Handover <<----> Patient
If this is what you want, the application of the predicate would be even shorter:
workplace.handovers.filteredSetUsingPredicate(
NSPredicate(format: "date > %@ && date < %@", startOfDay, endOfDay))