Можно ли использовать группу по счету в параметре hasPredicate для извлечения CoreData (для обнаружения обмана)?

Для справки проблема, которую я пытаюсь решить, – это эффективно находить и удалять дубликаты в таблице, в которой может быть много записей.

Таблица, с которой я работаю, называется PersistedDay с объектом dayString в ней (это строка.: -P). Есть больше столбцов, которые не имеют отношения к этому вопросу. Я бы хотел найти любой PersistedDay, у которого есть дубликаты.

В SQL это один из эффективных способов, которым вы можете это сделать (FYI, я могу сделать этот запрос в базе данных SQLite с поддержкой CoreData):

SELECT ZDAYSTRING FROM ZPERSISTEDDAY GROUP BY ZDAYSTRING HAVING COUNT(ZDAYSTRING) > 1; 

Это возвращает ТОЛЬКО значение dayStrings, у которого есть дубликаты, и вы можете получить все поля для этих объектов, запросив используя полученные дневные строки (вы можете использовать его в качестве вспомогательного запроса, чтобы сделать все это одним запросом).

У NSFetchRequest есть все необходимые части, чтобы сделать это тоже, но это не совсем похоже на работу. Вот что я пытался сделать:

 NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"PersistedDay" inManagedObjectContext:context]; [request setEntity:entity]; NSPropertyDescription* dayStringProperty = entity.propertiesByName[@"dayString"]; request.propertiesToFetch = @[dayStringProperty]; request.propertiesToGroupBy = @[dayStringProperty]; request.havingPredicate = [NSPredicate predicateWithFormat: @"dayString.@count > 1"]; request.resultType = NSDictionaryResultType; NSArray *results = [context executeFetchRequest:request error:NULL]; 

Это не работает. 😛 Если я попробую, то получаю сообщение об ошибке «Неподдерживаемый выражение выражения функции: (dayString)» при попытке выполнить выборку. Я не думаю, что dayString в «dayString. @ Count» даже имеет значение в этом коде выше … но я поставил его для ясности (подсчет SQL работает только сгруппированными строками).

Итак, мой вопрос: возможно ли это, и если да, то для чего это синтаксис? Я не мог найти ничего в документах CoreData, чтобы указать, как это сделать.

Я нашел одно подобное сообщение SO, которое, к сожалению, я, к сожалению, не могу найти снова, что было связано с запуском подсчета в условии наличия (я не думаю, что была группа). Но плакат сдался и сделал это по-другому, не найдя решения. Я надеюсь, что это более ясно, поэтому, возможно, у кого-то есть ответ. 🙂

Для справки, это то, что я делаю на данный момент, когда DOES работает, но требует возвращения почти всех строк, так как в большинстве случаев имеется очень мало дубликатов:

 NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"PersistedDay" inManagedObjectContext:context]; [request setEntity:entity]; NSPropertyDescription* dayStringProperty = entity.propertiesByName[@"dayString"]; // Get the count of dayString... NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"dayString"]; // Does not really matter NSExpression *countExpression = [NSExpression expressionForFunction: @"count:" arguments: [NSArray arrayWithObject:keyPathExpression]]; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; [expressionDescription setName: @"dayStringCount"]; [expressionDescription setExpression: countExpression]; [expressionDescription setExpressionResultType: NSInteger32AttributeType]; request.propertiesToFetch = @[dayStringProperty, expressionDescription]; request.propertiesToGroupBy = @[dayStringProperty]; request.resultType = NSDictionaryResultType; NSArray *results = [context executeFetchRequest:request error:NULL]; 

Затем мне нужно перебрать результат и вернуть результаты, которые имеют dayStringCount> 1. Это то, что должно делать предложение having. :-П

ПРИМЕЧАНИЕ. Я знаю, что CoreData не является SQL. 🙂 Просто хотел бы знать, могу ли я сделать эквивалентный тип операции с той же эффективностью, что и SQL.

3 Solutions collect form web for “Можно ли использовать группу по счету в параметре hasPredicate для извлечения CoreData (для обнаружения обмана)?”

Да, это возможно. Вы не можете ссылаться на count качестве ключевого пути, однако вы можете ссылаться на него как переменную. Также как в SQL. В моем примере у меня есть города, созданные с повторяющимися именами.

 let fetchRequest = NSFetchRequest(entityName: "City") let nameExpr = NSExpression(forKeyPath: "name") let countExpr = NSExpressionDescription() let countVariableExpr = NSExpression(forVariable: "count") countExpr.name = "count" countExpr.expression = NSExpression(forFunction: "count:", arguments: [ nameExpr ]) countExpr.expressionResultType = .Integer64AttributeType fetchRequest.resultType = .DictionaryResultType fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "name", ascending: true) ] fetchRequest.propertiesToGroupBy = [ cityEntity.propertiesByName["name"]! ] fetchRequest.propertiesToFetch = [ cityEntity.propertiesByName["name"]!, countExpr ] // filter out group result and return only groups that have duplicates fetchRequest.havingPredicate = NSPredicate(format: "%@ > 1", countVariableExpr) 

Полный файл детской площадки по адресу: https://gist.github.com/pronebird/cca9777af004e9c91f9cd36c23cc821c

Лучшее, что я могу придумать, это:

 NSError* error; NSManagedObjectContext* context = self.managedObjectContext; NSEntityDescription* entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context]; // Construct a count group field NSExpressionDescription* count = [NSExpressionDescription new]; count.name = @"count"; count.expression = [NSExpression expressionWithFormat:@"count:(value)"]; count.expressionResultType = NSInteger64AttributeType; // Get list of all "value" fields (only) NSPropertyDescription* value = [entity propertiesByName][@"value"]; NSFetchRequest* request = [[NSFetchRequest alloc] initWithEntityName:@"Event"]; request.propertiesToFetch = @[ value, count]; request.propertiesToGroupBy = @[ value ]; request.resultType = NSDictionaryResultType; NSArray* values = [context executeFetchRequest:request error:&error]; // Filter count > 1 values = [values filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"count > 1"]]; // slice to get just the values values = [values valueForKeyPath:@"value"]; 

Но это не сильно отличается от того, что вы используете.

Лучший способ поиска дубликатов в данных ядра зависит от ваших данных. Согласно « Эффективно импортировать данные» и предполагая, что вам нужно импортировать менее 1000 PersistedDays, я предлагаю это решение:

 NSFetchRequest* fetchRequest = [NSFetchRequest new]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"PersistedDay" inManagedObjectContext:myMOC]]; [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"dayString" ascending:NO]]]; NSArray* persistedDays = [myMOC executeFetchRequest:fetchRequest error:nil]; for (NSUInteger i = persistedDays.count - 1; i > 0; --i) { PersistedDay *currentDay = persistedDays[i]; PersistedDay *nextDay = persistedDays[i-1]; if ([currentDay.dayString isEqualToString:nextDay.dayString]) { /* Do stuff/delete with currentDay */ } } 

Для ускорения можно индексировать dayString в Core Data.

Вы также можете уменьшить набор данных, если вы помните отметку времени или дату очистки последнего дубликата:

 [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"importDate > %@", lastDuplicateCleanUp]; 
Interesting Posts

Как проверить, имеет ли пользователь действительный Auth Session Firebase iOS?

Динамическая высота для статических ячеек таблицы с оберткой?

QRCode из файла с использованием API IOS 7

'Неверное обновление: недопустимое количество строк в разделе 0

Apple ID не найден – In-App Purchase iOS 8

Вход с тестируемыми пользователями выходит из строя в режиме песочницы (iOS SDK)

iOS: обнаружение UIWebView достигает верхней или нижней

Как можно преобразовать, включая дату часового пояса, в swift?

Как сделать UIKeyboard черным?

Соединение Multipeer с одним устройством, работающим в фоновом режиме

Связать AVPlayerItem с новым AVPlayer в Swift?

Проблемы с достижимостью с момента обновления до iOS 6

Добавить UIActivityIndicatorView в UIActionSheet

Может ли приложение iOS читать свои собственные права во время выполнения?

Интересная совпадающая головоломка UIScrollView

PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.