CoreData 多对多查找重复项
CoreData Many-to-Many Find Duplicates
我正在研究一个谓词来搜索与任何其他用户具有相同偏好的用户
用户 <<->> 首选项
给定以下状态;我想查询新注册用户
(Sam, nickname: "foo", language: "english")
查看是否有任何现有用户具有相同的偏好。可以有任意数量的首选项类型。在这种情况下,它将检测到 Sally 具有相同的选择
用户
| Name |
| Sally |
| John |
偏好类型
| Name |
| nickname |
| language |
| .... |
用户首选项
User PreferenceTypes Selection
Sally | nickname | "foo"
Sally | language | "english"
John | nickname | "bar"
John | language | "english"
如果你想检查昵称是否已经存在,你可以尝试这样的事情(如果我理解你的模型是正确的)
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"UserPreferences"
inManagedObjectContext:context]];
[NSPredicate predicateWithFormat:@"Selection == %@ AND PreferenceTypes == 'nickname'", newUser.nickname]
NSArray *ary = [context executeFetchRequest:fetchRequest error:&err];
if(ary && ary.count > 0)
{
// handle "user exists" case
}
else
{
// handle "create user" case
}
我希望这就是您要找的。如果我对你的问题的理解有误或者它不起作用,请告诉我 ;)
您可以这样设置模型:
User <---->> Preference <<-----> PreferenceType
User.name // name string
User.preferences // to-many to Preference
Preference.value // the value, or "selection"
Preference.user // to-one to User
Preference.type // to-one to PreferenceType
Preference.name // name of preference, such as "language"
PreferenceType.preferences // to-many relationship to Preference
您的谓词将需要一个子查询,并且在资源使用方面相当 "expensive"。我假设允许某些用户拥有其他用户没有的偏好,即虽然我们知道可能偏好的总数,但我们不知道某个特定用户拥有的偏好数量。我不能从头顶写出那个查询,我必须考虑一下。 --- 有人吗?
一种实用的方法是首先获取用户的一个子集,比如说那些昵称完全相同的用户。使用像这样的谓词获取偏好对象会更简单:
[NSPredicate predicateWithFormat:
@"type.name = 'nickname' && value = %@ && not (user = %@)", userNickname, user];
对于一小部分用户(由 foundPreference.user
引用),您可以 运行 您编写的自定义方法 (hasSamePreferences
),您可以在其中遍历首选项并检查是否存在和平等。
-(BOOL)hasSamePreferencesAsUser:(User*)otherUser {
NSSet *myPreferenceKeys = [self.preferences valueForKeyPath:@"type.name"];
NSSet *otherPreferenceKeys = [otherUser.preferences valueForKeyPath:@"type.name"];
if (myPreferenceKeys.count != otherPreferenceKeys.count) {
return NO;
}
for (NSString *key in myPreferenceKeys) {
if (![otherPreferenceKeys containsObject:key]) {
return NO;
}
NSPredicate *keyFilter = [NSPredicate predicateWithFormat:@"type.name = %@", key];
// String only for demonstration
NSString *myValue = [self.preferences
filteredArrayUsingPredicate:keyFilter].firstObject;
NSString *otherValue = [otherUser.preferences
filteredArrayUsingPredicate:keyFilter].firstObject;
if (![myValue isEqualToString:otherValue]) {
return NO;
}
}
return YES;
}
顺便说一句,如果您不期望超过 20 个首选项,那么它将更加务实并将这些首选项作为正确命名的属性硬编码到 User
(或具有 Settings
的实体如果您愿意,可以建立一对一的关系)。您的代码将非常可读,并且您的谓词相当微不足道。
我正在研究一个谓词来搜索与任何其他用户具有相同偏好的用户
用户 <<->> 首选项
给定以下状态;我想查询新注册用户
(Sam, nickname: "foo", language: "english")
查看是否有任何现有用户具有相同的偏好。可以有任意数量的首选项类型。在这种情况下,它将检测到 Sally 具有相同的选择
用户
| Name |
| Sally |
| John |
偏好类型
| Name |
| nickname |
| language |
| .... |
用户首选项
User PreferenceTypes Selection
Sally | nickname | "foo"
Sally | language | "english"
John | nickname | "bar"
John | language | "english"
如果你想检查昵称是否已经存在,你可以尝试这样的事情(如果我理解你的模型是正确的)
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"UserPreferences"
inManagedObjectContext:context]];
[NSPredicate predicateWithFormat:@"Selection == %@ AND PreferenceTypes == 'nickname'", newUser.nickname]
NSArray *ary = [context executeFetchRequest:fetchRequest error:&err];
if(ary && ary.count > 0)
{
// handle "user exists" case
}
else
{
// handle "create user" case
}
我希望这就是您要找的。如果我对你的问题的理解有误或者它不起作用,请告诉我 ;)
您可以这样设置模型:
User <---->> Preference <<-----> PreferenceType
User.name // name string
User.preferences // to-many to Preference
Preference.value // the value, or "selection"
Preference.user // to-one to User
Preference.type // to-one to PreferenceType
Preference.name // name of preference, such as "language"
PreferenceType.preferences // to-many relationship to Preference
您的谓词将需要一个子查询,并且在资源使用方面相当 "expensive"。我假设允许某些用户拥有其他用户没有的偏好,即虽然我们知道可能偏好的总数,但我们不知道某个特定用户拥有的偏好数量。我不能从头顶写出那个查询,我必须考虑一下。 --- 有人吗?
一种实用的方法是首先获取用户的一个子集,比如说那些昵称完全相同的用户。使用像这样的谓词获取偏好对象会更简单:
[NSPredicate predicateWithFormat:
@"type.name = 'nickname' && value = %@ && not (user = %@)", userNickname, user];
对于一小部分用户(由 foundPreference.user
引用),您可以 运行 您编写的自定义方法 (hasSamePreferences
),您可以在其中遍历首选项并检查是否存在和平等。
-(BOOL)hasSamePreferencesAsUser:(User*)otherUser {
NSSet *myPreferenceKeys = [self.preferences valueForKeyPath:@"type.name"];
NSSet *otherPreferenceKeys = [otherUser.preferences valueForKeyPath:@"type.name"];
if (myPreferenceKeys.count != otherPreferenceKeys.count) {
return NO;
}
for (NSString *key in myPreferenceKeys) {
if (![otherPreferenceKeys containsObject:key]) {
return NO;
}
NSPredicate *keyFilter = [NSPredicate predicateWithFormat:@"type.name = %@", key];
// String only for demonstration
NSString *myValue = [self.preferences
filteredArrayUsingPredicate:keyFilter].firstObject;
NSString *otherValue = [otherUser.preferences
filteredArrayUsingPredicate:keyFilter].firstObject;
if (![myValue isEqualToString:otherValue]) {
return NO;
}
}
return YES;
}
顺便说一句,如果您不期望超过 20 个首选项,那么它将更加务实并将这些首选项作为正确命名的属性硬编码到 User
(或具有 Settings
的实体如果您愿意,可以建立一对一的关系)。您的代码将非常可读,并且您的谓词相当微不足道。