I'm working on an app where I have Post objects, each Post can have many Entities (mentions, hashtags and links), each Entity have one Post. I have one main class for Entity, then I have three subclasses.
Mention : Entity
My mention class have the following properties:
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * userId;
I now want to create a NSPredicatethat finds all Posts that are mentioning a certain User and userId, and I'm not sure how I should do that.
I have tried some things like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY mentions.userId like %#", [Session currentUser].userId];
// That doesn't work since Post(s) have many entities and not Mention(s).
// I have also tried something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY entities.mentions.userId like %#", [Session currentUser].userId];
// And that didn't work either.
Any ideas on how I best should find all posts that are mentioning a certain user with a specific userId?
Inheritance is there so you do not have to code equal attributes twice. Otherwise, managed objects with parent objects are just like other managed objects.
Therefore, you should give your posts three relationships:
Post
hashes Hash
mentions Mention
links Link
Then your problem becomes trivial:
[NSPredicate predicateWithFormat:#"ANY hashes.userID = %#", _currentUser.userID];
Like does not make sense, as userID is presumably unique, and LIKE is much more expensive than simple equivalence.
If you want just one to-many relationship to one class of entity you will have to include another attribute in Entity, e.g. an NSNumber, to indicate what type it is. The predicate would then be as follows, assuming you use an enum to make the number types more readable:
[NSPredicate predicateWithFormat:
#"ANY (entity.type == %# && entity.userID == %#)",
#(EntityTypeMention), _currentUser.userID];
Related
Considering Action with an assignedTo relationship to User entity. (Action.assignedTo->>User)
What would be a query that selects all actions which contain the user in the assignedTo set?
Subquery is a bit heavy handed.
You can use this :
[NSPredicate predicateWithFormat:#"ANY assignedTo.userId == %#", user.userId];
I found that SUBQUERY is the right answer here; it works perfect:
[NSPredicate predicateWithFormat:
#"(SUBQUERY(assignedTo, $a, $a.userId == %ld).#count != 0)", user.userId];
and with filter by status
[NSPredicate predicateWithFormat:
#"(SUBQUERY(assignedTo, $a, $a.userId == %ld).#count != 0) && status != 'Completed'", user.userId];
Did you create your model files using the Xcode generator for CoreData?
If so, check your User.h file, you should see something like this:
#property (nonatomic, retain) NSSet *actions;
That mean that you can call all the actions of that user just calling:
NSSet *userActions = user.actions;
No need to use a predicate.
If still you want to use a predicate, the predicate should look like this:
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:#"assignedTo == %#",user];
If you need to add aditional predicates you should you an array of them a make a NSCompoundPredicate:
NSPredicate *anotherPredicate= ...;
//andPredicateWithSubpredicates if you want the both
//orPredicateWithSubpredicates if you want at least one of them
NSPredicate *compoundPredicate = (NSPredicate*)[NSCompoundPredicate andPredicateWithSubpredicates:#[userPredicate,anotherPrediate]]
Suppose I have the following objects
class A {
NSArray *arrayOfB;
}
class B {
NSString *name;
}
Now, I have an array of As like below and each A contains 10 objects of B within its property arrayOfB.
NSArray *arrayOfAs; //contains objects of A
How can I get the objects of A depending upon specific match of name property of Bs inside of A, by using NSPredicate ?
I've tried googling, etc. and even writing various style of NSPredicate but did not succeed. Can anyone enlighten me how to do it?
This is what I tried so far:
NSPredicate *p = [NSPredicate predicateWithFormat:#"(SELF.name BEGINSWITH[c] %# IN SELF.arrayOfB)",myText];
NSArray *mySearchedArrayOfAs = [arrayOfAs filteredArrayUsingPredicate:p];
But I run into error which says "Unable to parse the predicate".
I think you need to use ANY operator, like this:
NSPredicate *p = [NSPredicate predicateWithFormat:#"ANY arrayOfB.name BEGINSWITH[c] %#", myText];
I have a model object Place that have a couple of standards properties. It also have some custom instance method defined in a Mogenerated subclass. That looks something like this:
- (NSString *) currentName {
return [self valueFromArrayData:self.nameLocaleMap atIndex:...];
}
I wonder if it's possible to make a NSpredicate would function something like this somehow:
// I have tried this predicate, and it doesn't work... IS it possible to do something similar to get the wanted effect?
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"currentName CONTAINS[cd] %#", searchText];
Or alternatively, if it's possible to evaluate/compare the contents of a NSData property with a NSString?
Your predicate should work, but only when run locally against, for example, an array (filteredArrayUsingPredicate:).
Your predicate can not be used with Core Data because currentName doesn't exist at the data store level.
I have an NSMangedObject that contains NSSet of other NSManagedObjects.
I need to check if these objects has an value in NSSet and then return them.
I use MagicalRecord for fetching data.
So I need something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"stringObjects contains %#", string];
So if NSSet stringObjects contains some string that I am looking for so then return object I have requested.
One note here: stringObjects (name just for example it represent my NSSet) it is NSSet that contains NSManagedObjects, so I need to search them by some id (for example string_id attribute).
So then model looks like this
NSSet *set = MainObject.stringObjects;
NSString *string_id_for_first_object = [[[set allObjects] objectAtIndex:0] string_id];
Just for better understanding relationship.
But the question is about how can I create predicate to check if NSSet contains needed id.
If I understand your question correctly, stringObjects is a to-many relationship
from one entity A to another entity B, and B has an attribute string_id.
To find all A objects that are related to any B object with the given string id, use:
NSString *stringId = …; // The string that you are looking for
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY stringObjects.string_id == %#", stringId];
EntityA has a to-many relationship to EntityB (and EntityB has a to-one relationship to EntityA). I have an array of EntityBs (or more accurately, I have an NSArray that contains instances of NSManagedObject which represent EntityB). I want to create an NSFetchRequest that will fetch all EntityAs that have a relationship to at least one of the EntityBs in the array. How do I write the predicate for this fetch request?
The following works, but I think it is sub-optimal; it's hard to grok and I'm sure there must be a better way of expressing this:
NSArray *entityBs = ...;
NSMutableArray *containsEntityBSubPredicates = [NSMutableArray new];
for (NSManagedObject *entityB in entityBs) {
[containsEntityBSubPredicates addObject:[NSPredicate predicateWithFormat:#"%# IN entityBs", entityB]];
}
NSPredicate *containsEntityBsPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:containsEntityBSubPredicates];
I've also tried this, but it doesn't work:
NSArray *entityBs = ...;
NSPredicate *containsEntityBsPredicate = [NSPredicate predicateWithFormat:#"ANY %# in entityBs", entityBs];
Am I missing a simpler solution?
You were almost there with your predicate, just switch the parameters:
[NSPredicate predicateWithFormat:#"ANY entityBs in %#", entityBArray];
Look at Apple's example code with IN here for further explanation.