Reputation: 9140
I have a core data object like this:
I build a predicate to get scheduletimes and per selection times I need to get the movies and theaters
With the value of the schedule I tried to get theater
Here is my code:
NSString *nameOfMovie = [[scheduleResults movie] valueForKey:@"nameOfMovie"];
NSPredicate *theaterPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY (showTimes, $x, $x.nameOfMovie == %@ AND $x.showTimes.showTimes == %@).@count > 0", nameOfMovie, showTimes];
But I'm getting this error with my predicate:
to-many key not allowed here
any of you knows what I'm doing wrong with my predicate?
Upvotes: 0
Views: 99
Reputation: 21154
I found the question quite interesting and so create a simple playground with swift to test the subquery for your case. I think you are missing some relations in your data model, if you really care about it, and you should name the entities in singular like Movie, Schedule, Theater etc which makes more sense, since entities are always singular and associations can be singular or plural depending on one-to-many or one-to-one relation.
Here is what I have come up with the data model,
// a Movie can have multiple schedule and a schedule can have multiple movies at the same time
Schedule << ------- >> Movie
// a Movie can be running in multiple theater and a theater can have multiple movies
Movie << ------>> Theater
So, based on the above relation, I created a playground file to create some fixture data and play around,
class Schedule: NSObject {
var showTime: NSDate!
var movies: [Movie]!
}
class Theater: NSObject {
var name: String!
var movies: [Movie]!
}
class Movie: NSObject {
var nameOfMovie: String!
var theaters: [Theater]!
var showTimes: [Schedule]!
}
let hitech = Theater()
hitech.name = "Hitech Cinema"
let kino = Theater()
kino.name = "Kino"
let warner = Theater()
warner.name = "Warners"
let interstellar = Movie()
interstellar.nameOfMovie = "Interstellar"
let gravity = Movie()
gravity.nameOfMovie = "Gravity"
let wrathOfSpace = Movie()
wrathOfSpace.nameOfMovie = "Wrath of Space"
let today = NSDate()
let yesterday = today.dateByAddingTimeInterval(-60 * 60 * 24)
let tomorrow = today.dateByAddingTimeInterval(60 * 60 * 24)
let todaySchedule = Schedule()
todaySchedule.showTime = today
let yesterdaySchedule = Schedule()
yesterdaySchedule.showTime = yesterday
let tomorrowSchedule = Schedule()
tomorrowSchedule.showTime = tomorrow
todaySchedule.movies = [interstellar, gravity]
tomorrowSchedule.movies = [interstellar, wrathOfSpace]
yesterdaySchedule.movies = [wrathOfSpace, gravity]
interstellar.showTimes = [todaySchedule, tomorrowSchedule]
gravity.showTimes = [todaySchedule, yesterdaySchedule]
wrathOfSpace.showTimes = [tomorrowSchedule, yesterdaySchedule]
interstellar.theaters = [kino, hitech]
gravity.theaters = [kino, warner]
wrathOfSpace.theaters = [warner, hitech]
kino.movies = [interstellar, gravity]
hitech.movies = [interstellar, wrathOfSpace]
warner.movies = [wrathOfSpace, gravity]
let theaters:NSArray = [hitech, warner, kino]
var nameOfMovie = "Gravity"
var date = yesterday
var predicate = NSPredicate(format: "SUBQUERY(movies, $a, $a.nameOfMovie = %@ and SUBQUERY($a.showTimes, $b, $b.showTime = %@).@count > 0).@count > 0", nameOfMovie, date)
let threatersYesterdayGravity = theaters.filteredArrayUsingPredicate(predicate)
nameOfMovie = "Interstellar"
date = tomorrow
predicate = NSPredicate(format: "SUBQUERY(movies, $a, $a.nameOfMovie = %@ and SUBQUERY($a.showTimes, $b, $b.showTime = %@).@count > 0).@count > 0", nameOfMovie, date)
let threatersTomorrowInterstellar = theaters.filteredArrayUsingPredicate(predicate)
And the result are as I would expect. You can also play with the above relation and subquery fit it to your need.
Upvotes: 1