I have three realm objects. Department, section and user. section is a kind of sub department in a department. But there will be users under each section and each department.
@interface Department : RLMObject
@property NSString *name;
@property BOOL isCollapsed;
@property (nonatomic, strong) RLMArray<Section> *sections;
@property (nonatomic, strong) RLMArray<User> *users;
@end
@interface Section : RLMObject
@property NSString *name;
@property BOOL isCollapsed;
@property RLMArray<User> *users;
@end
@interface User : RLMObject
@property NSString *department;
@property NSString *email;
@property NSString *firstname;
@property NSString *lastname;
@property NSString *fullname;
@end
What i want to do is, I want to search all the user whose first name and last name contains "a" and linked with department and section.
Now what i am doing is
searchText = [searchText lowercaseString];
RLMResults *sections = [Section objectsWhere:
[NSString stringWithFormat:@"SUBQUERY(users, $user, $user.fullname contains '%@' OR $user.nickname contains '%@').@count > 0",searchText,searchText]];
NSMutableArray *sectionNames = [NSMutableArray array];
for (Section *section in sections)
{
[sectionNames addObject:section.name];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(sections, $section, $section.name IN %@).@count > 0", sectionNames];
RLMResults *filteredDepartments = [[Department objectsWithPredicate:predicate] sortedResultsUsingProperty:@"name" ascending:YES];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SUBQUERY(users, $user, $user.fullname contains %@ OR $user.nickname contains %@).@count > 0",searchText,searchText];
RLMResults *departments = [filteredDepartments objectsWithPredicate:pred];
Right now the issue is there is two sections in sections array but in the deparments results, it returns null. please help. thanks.
Note: If one user already belongs to section then that user will not be include in department.
Maybe you do not need to use subquery. More simply, you can use ANY
in query like the following:
[Department objectsWhere:
@"ANY users.firstname CONTAINS %@ OR ANY users.lastname CONTAINS %@ OR ANY sections.users.firstname CONTAINS %@ OR ANY sections.users.lastname CONTAINS %@", searchText, searchText, searchText, searchText];
But I think using inverse relationships is more easier. In Realm, inverse relationships is defined with RLMLinkingObjects
.
You can add inverse relationships to User
class as follows:
@interface User : RLMObject
...
@property (readonly) RLMLinkingObjects *departments;
@property (readonly) RLMLinkingObjects *sections;
@end
@implementation User
+ (NSDictionary *)linkingObjectsProperties {
return @{@"departments": [RLMPropertyDescriptor descriptorWithClass:Department.class propertyName:@"users"],
@"sections": [RLMPropertyDescriptor descriptorWithClass:Section.class propertyName:@"users"]};
}
@end
Then you can get departments and sections where the user belongs to from User
's property, like the following:
RLMResults *users = [User objectsWhere:@"firstname CONTAINS %@ OR lastname CONTAINS %@" , searchText, searchText];
for (User *user in users) {
NSLog(@"%@", user.departments);
NSLog(@"%@", user.sections);
}