I have a model with following structure:
- Document entity has many Commands
-
Command belongs to Document
-
Document has many Tags
- Tag has many Documents
This is important because of additional table used for this type of relation
Tag has also a type property which is an integer being an enum.
What I try to achieve is to ask CoreData for a Commands that belong to Documents which do not have a relation with a tag of type TagTypeUnwanted, in a single query obviously 🙂
I tried to make a subquery with a predicate:
[NSPredicate predicateWithFormat:@"SUBQUERY(document.tags, $tag, $tag.type == %d).@count == 0", TagTypeUnwanted]
unfortunatelly it tries to join with the middle-table that manages the relation between Document and Tag. So it results in complaining that it cannot find filed ‘type’ there, because it has only Document id and Tag id and this is not what I expected. It looks like it would work for every other relation than many-to-many, in this case however it’s lost.
[NSPredicate predicateWithFormat:@"NOT ANY document.tags.type == %d", TagTypeUnwanted]
this one also doesn’t work as it leaves only NOT in the SQL and it reaults in every Document being found because of relations with many types of tags. So it will always find at least one record where type is NOT type TagTypeUnwanted.
If you like more info or generated SQL or anything, just write it in a comment. Thanks in advance!
Looks like NOT ANY and NONE both are not working in Core Data, as far as I was able to check it is a known issue since 2007, normally you do subquery to workaround this, but it seems like subquery in this case cannot handle many-to-many table
NOT ANY generates: AND NOT (Tag.type == TagTypeUnwanted) so it is only close to how SQL should really look
This is perhaps not very effective, but it might be interesting that the following nested SUBQUERY seems to work: