OK so looked for answers and I'm probably making some assumption that others aren't and thats why the solution is working for them.
Problem:
Lets say I have an Entity called DogOwner. A dog owner can have multiple Dogs and each dog can have multiple Wearables. Note that all relationships are optional and one-to-many (inverse many-to-one).
Aim:
Search all the dog owners that own a dog that has a Wearable type GpsTracker and contains id of 898764.
My approach:
Fetching the entity DogOwner with the following predicate
NSPredicate(format: "(dog.wearable.type == %#) AND (dog.wearable.external_id CONTAINS[cd] %#)", theType, theIdentifier)
I get an unimplemented SQL generation for predicate error.
Tried -> with ANY (Nested core data fetch)
Tried other stuff present on the Internet. Nothing as far I have seen works, I assume that the problem is deeper down given that nested tree structured graph is being successfully queried by others using the dot notation.
While subquery is a feasible way to do this it is exceedingly complicated, and unnecessarily so. Why not simply search for the specific Wearable and get the owner via the convenient to-one relationships?
// fetch wearable with id x
let owner = wearable.dog.owner
I think you need to use SUBQUERY, if only because you need to test both conditions simultaneously:
NSPredicate(format: "SUBQUERY(dog, $d, SUBQUERY($d.wearable, $w, $w.type == %# AND $w.external_id CONTAINS[cd] %#).#count > 0).#count > 0", theType, theIdentifier)
Or "fetch DogOwners having more than 0 dogs having more than 0 wearables matching the criteria".
Related
I'm new relationship on core data and do not know what's going on. I have a many to many relationship between the News and Friends entity as shown below:
News <<------------>> Friends
Where relationships are respectively:friends (in News) and news (on Friends)
Created NSManagedObject Subclass but did not change anything (do not know if it is essential to work the relationship) and also think it is not necessary popular this relationship since the two entities already have dados.E I discovered that the relationship is empty using:
let predicate = NSPredicate(format: "any friends.friendship.#count == %d" , 0)
where friendship is a Friends attribute ,and also I tried:
let predicateDenuncia = NSPredicate(format: "any friends.#count == %d" , 0)
That way I discovered my relationship is returning empty, because when equated to zero the condition of true and are shown the news ..... someone there knows what might be happening? Thank you.
I have a core data model like this:
and I'm trying to query all the movies showing a theater with particular schedule.
But I can not figure out how can I this query with NSPredicate.
I tried this:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:#"SUBQUERY (movies, $x, $x.movies.showTimes == %# AND $x.movies.theater.nameOfTheater == %#).#count >0", showTime, theater];
but didn't work. Any of you knows what I'm doing wrong?
I'll really appreciate your help
I'm assuming from your stated objective ("... query all the movies showing a theater with particular schedule") that the entity for your NSFetchRequest is Movies. If so, the attribute and relationship names you use should all be relative to that entity. Hence the theatre name will be given by theaters.nameOfTheater and the show times will be showTimes.showTimes. Because there are many Schedules for a given Movie, your predicate needs to select a movie if ANY of the showTimes.showTimes match your requirement. So one way to write the predicate would be:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:#"theaters.nameOfTheater == %# AND (ANY showTimes.showTimes == %#)", theater, showTime];
Alternatively, the ANY clause can be rewritten as a SUBQUERY:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:#"theaters.nameOfTheater == %# AND SUBQUERY(showTimes, $x, $x.showTimes == %#).#count > 0", theater, showTime];
As a broader recommendation, I would make some changes the names of your attributes and entities; it will help to make things clearer:
Entity names should generally be singular, so Movie not Movies, Theatre not Theatres and Schedule not Schedules.
Likewise the names of relationships should reflect whether they are to-one or to-many. So the Movie entity should have a relationship theatre since it is to-one, and the Schedule entity should have a relationship movies since it is to-many.
Finally, I think you could improve your data model. Currently, each Movie can have only one Theater. In practice, I would imagine that a movie will be shown at more than one theater! Personally, I would have a model like this:
So each Schedule relates to only one Movie and one Theater. But each Theater has many showings, and each Movie has many screenings. Using this model, the predicate to meet your query would be:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:#"SUBQUERY(screenings, $x, $x.theater.nameOfTheater == %# AND $x.showTime == %#).#count > 0", theater, showTime];
I have following entities:
PBOUser, PBOBusiness and PBOLocation.
PBOUser may have a lot of businesses.
PBOBusiness may have a lot of locations.
PBOLocation may belong to only one business.
PBOBusiness may belong to many users.
I need to find these locations which belong to those businesses that my user owns.
let predicate = NSPredicate(format: "business IN %#", myUser.businesses)
let locations = PBOLocation.MR_findAllWithPredicate(predicate) as? [PBOLocation]
But it doesn't work. How to do this in a quick way?
If you ever wanted to do it as a query you would need to use a SUBQUERY predicate
let predicate = NSPredicate(format: "SUBQUERY(business.users, $user, $user == %#).#count > 0", myUser)
business.users is the keyPath to the collection whose elements you want to test
Each item in the collection is evaluated agains the predicate $user == %#
When each item is evaluated against the predicate we use $user to make that the variable name for the single element to use in the predicate
The SUBQUERY will return a collection of results that match so to summarise we use #count > 0 to say if there was at least one match then this fits our criteria
You could probably come up with a predicate that works. But since you already have a reference to PBOUser, you're making things harder than they need to be. Consider that
PBOUser has a relationship to PBOBusiness
PBOBusiness has a relationship toPBOLocation`
With these relationships, a user's businesses are myUser.businesses, as in your code snippet. So take that one step farther and use the fact that locations are a property of the businesses:
let locations = myUser.businesses.valueForKey("location") as NSSet
This makes use of the fact that valueForKey on an array or set will call valueForKey on each member of the collection, and return the results as the same kind of collection. That's why it's an NSSet-- if you want a sorted array, add a call to sortedArrayUsingDescriptors:.
I'm trying to build a predicate that compares two members of a too-many relationship.
The code below more clearly shows my intention, but doesn't seem to work (assume objects is the too-many relationship and has members, member1 and member2):
[NSPredicate predicateWithFormat:
#"(ANY objects.member1 ==[cd] objects.member2)"];
I appreciate any help in determining a properly structured predicate for this type of comparison.
Assuming that you want to fetch the objects which are related to at least one object with
"member1 == member2", you have to use a SUBQUERY:
[NSPredicate predicateWithFormat:#"SUBQUERY(objects, $o, $o.member1 == $o.member2).#count > 0"]
You can find a similar example in the NSExpression Class Reference.
Im trying to implement something that I'm sure have been implemented a million times before, a search in the core data database, displayed in a table using a fetchRequestController and the searchController.
My problem is writing the NSPredicate for the NSFetchRequest. According to the NSPredicate guide by Apple, not everything you can do in Sqlite is possible with core data.
I have been trying to find a solution for some time, but maybe one of you can use his experience to help me.
CoreData DB description:
Shops has a MANY TO MANY relationship with DiscountProgam.
My use case is as follows: I need to filter out Shops who's name/address/zip/city contains the search string. that's the easy part.
The hard part is creating the section of the database I want to filter from, because I have an array of "active" discountPrograms UID's, and I only want shops that have one of the active discount programs in their "discountPrograms" set. So in pseudo code that would be:
FROM Shops who have at least one discountProgram who's uid IN activeDiscountProgramsArray WHERE name/address/zip/city CONTAINS searchString
Is this possible? am I over reaching the limits of predicates?
If so, how could I do it differently?
Yes, NSPredicate can analyse both the direct attributes of the target entity of a fetch and the attributes of its relationships. Try:
NSArray *validUIDs = ...;
NSString *searchTerm = ...;
[NSPredicate predicateWithFormat:#"(name CONTAINS[cd] %# OR zip CONTAINS[cd] %#) AND (SUBQUERY(discountProgram, $d, $d.UID IN %#).#count > 0)", searchTerm, searchTerm, validUIDs];