Можно ли использовать группу по счету в параметре 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

Как предотвратить переполнение регулируемой высоты tableview cell при удалении

обновление профиля и сертификатов

Передача событий касания к соответствующим UIViews братьев и сестер

Невозможно заставить новые AppLinks работать на iOS или Android

AFNetworking не создает правильный URL?

Как вызвать методы iKarte SDK для сканирования RFID

Радиус угла стола TableView отличается от iOS6

removeItemAtPath – ошибка: не удалось удалить, поскольку у вас нет доступа к ней

Swift: UISearchBar: получить текст при нажатии кнопки поиска

Как создать специальную сеть из iOS

Для интеграции iAd требуется регистрация или настройка объявлений?

Когда я обновляю свою игру в iTunes connect, список лидеров будет перенесен?

UITesting Failure получает список активных приложений

NSStream, получая процент прочитанных байтов

AFNetworking не может возобновить загрузку, когда установлено «Content-Encoding: gzip»

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