NSPredicate and KVC collection operators - core-data

Assume I have a Core Data class Employer with a 1-N relationship called employees.
This employees relationship maps to an NSSet. So far so good.
I want to create an NSFetchRequest of Employer with a predicate that requieres that employees > 0.
How can I create this predicate?
I tried "employees.#count", but it seems to consider the whole thing a keyPath.

You got the syntax backwards:
#count.employees

Related

How to filter entities by to-one relationship in Core Data.

In my function unit, I got an entity author's record. I need find out all books written by this author.
The Book has a relationship called belongToAuthor. How to request book records?
Can I use following NSPredicate to filter books by author relationship?
Author *author;
author = _author;
NSPredicate* predicate = [NSpredicate predicateWithFormat:#"ANY book.belongToAuthor == %#", author];
If you've followed the Core Data design principles, your relationship belongToAuthor (by the way, simply calling it author might be a much better name) has an inverse relationship on the Author class pointing the Bookclass - named something simple like books.
Book.belongToAuthor <<-> Author.books
With that you can simply rely on the power of Core Data and get all books written by that author by calling
NSSet *books = author.books;
Related documentation: Core Data Programming Guide - Relationships

NSPredicate for items in two-levels deep to-many relationship, w/o direct relationship

I'm trying to build a single NSFetchRequest predicate for the following (simplified) model:
There is a simple to-many relationship between a Category and a number of Brands.
Each Brand then has a modelNumbersData property which is binary data, a serialisation of an array of NSString modelNumbers which are exposed in a transient property on the Brand objects.
There is no direct relationship between Brands and Models. The relationship is that a Model's modelNumber may be in a Brand's modelNumbers transient property.
I would like to build an NSPredicate query to fetch all of the Model objects under a particular Category.
Fetching the Models for a Brand is easy, I can do "modelNumber IN $FETCH_SOURCE.modelNumbers". How do I now extend this query to originate with the category? It seems I need a SUBQUERY?
Furthermore, I am doing an NSFetchRequest, so unless I'm mistaken I need to start with "SELF.modelNumber IN (...)", so that we select from all Models.
Thanks in advance!
Ok, I got there first. For reference, the following works:
SUBQUERY(%#.brands, $brand, $brand.modelNumbers CONTAINS $modelNumber).#count > 0
I think the problem I was mostly having was neglecting the .#count component. Still don't quite understand this, but it seems to be necessary with all SUBQUERY statements.

Related NSManagedObject in NSPredicate

In my NSFetchedResultsController I want to have an NSPredicate which only fetches objects with certain relationships.
For example:
I have three subclassed NSManagedObjects: Flight, Aircraft, Battery.
Every Flight has one Aircraft. Every Flight can have several Battery objects.
So when I am fetching the Flight objects, this is something I have tried with the predicate: [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"aircraft = %#", aircraftObj]];
So I only want to fetch the Flight objects which are related to that specific Aircraft object. This doesn't work, but how can I do this?
Secondly, building on that, the Flight has batteries which is an NSSet of Battery objects. So if I want to do the same as the Aircraft, but filter the Battery objects, how would I do this?
Thanks, let me know if I need to explain further.
You have a problem of "double formatting" your predicate.
You could simply write:
[NSPredicate predicateWithFormat:#"aircraft = %#", aircraftObj]
the same would go for your Battery objects (but with the proper Flight)

Core Data many-to-many predicate (again)

Yesterday I asked a question about a many-to-many relationship:
I have two entities which are related by a many-to-many relationship:
Database <<----->> Category
In other words, a database can have many categories and a category can
be associated with many databases.
I need an NSPredicate that will return all Category objects associated
with a given Database object.
...and received some very helpful advice. I would now like to ask a different, but related, question:
I would like an NSPredicate that will return all Category objects NOT associated with a given Database object.
I require this as a predicate since it is being used as part of a fetched results controller.
Any help greatly appreciated. Thanks in advance!
It seems to be a Core Data bug that "NOT ANY" queries do not work correctly
(see Core Data NSPredicate with to-Many Relationship for a similar issue).
As a workaround, you can use the following predicate with "SUBQUERY":
[NSPredicate predicateWithFormat:#"SUBQUERY(databases, $db, $db == %#).#count == 0", theDatabase]
Try to use:
[NSPredicate predicateWithFormat:#"NOT (ANY databases = %#)", database];
Or
[NSPredicate predicateWithFormat:#"NOT(%# IN databases)", database]

Core-Data CoreDataGeneratedAccessors vs. simple assignment

I have a 1-to-many relationship in a Core Data graph, and I'm trying to understand the difference between using a CoreDataGeneratedAccessors method and a simple assignment to alter a relationship. For example, the Core Data Programming Guide has a department and employee example. In that example they use the CoreDataGeneratedAccessors to hire and fire employees:
[aDepartment addEmployeesObject:newEmployee];
[aDepartment removeEmployeesObject:firedEmployee];
They don't define an inverse relationship, but say "department" is the inverse relationship to "employees". Should the following then accomplish the same thing?
newEmployee.department = aDepartment
firedEmployee.department = nil;
According to the Manipulating Relationships and Object Graph Integrity section of the Core Data Programming Guide, the later examples should automatically fix all relationships to maintain graph consistency. If that's the case, is there any reason to use the CoreDataGeneratedAccessors when an inverse relationship exists? Does using the CoreDataGeneratedAccessors maintain graph consistency on inverse relationships?
They don't define an inverse
relationship, but say "department" is
the inverse relationship to
"employees". Should the following then
accomplish the same thing?
Both operations have the same result no matter which end of the relationship (with inverse) you modify.
If that's the case, is there any reason to use the CoreDataGeneratedAccessors when an inverse relationship exists? Does using the CoreDataGeneratedAccessors maintain graph consistency on inverse relationships?
Consistency is not an issue with both methods.
For performance reasons it is very important to modify large relationships with apropriate methods.
Solution 1 (firing all employees of a department)
for (Employee* employee in aDepartment.employees)
{
employee.department = nil
}
Solution 2
aDepartment.employees = nil;
The first solution would trigger an update of a (table-)view after each operation while the second would result in exactly one update of all views.
This can be a big difference if you handle a a large amount of objects.
If you need more in depth information, I think similar topics have already been discussed on SO.

Resources