Dla porównania, problemem, który próbuję rozwiązać, jest skuteczne znajdowanie i usuwanie duplikatów w tabeli, która może zawierać wiele wpisów.Czy możliwe jest użycie grupy według liczenia w module havingPredicate w celu pobrania CoreData (w celu wykrycia dupe)?
Tabela, nad którą pracuję nazywa się PersistedDay z obiektem dayString (jest to ciąg. :-P). Więcej kolumn nie ma związku z tym pytaniem. Chciałbym znaleźć jakiekolwiek PerscedDay, które mają duplikaty.
W SQL, jest jednym z efektywnych sposobów można to zrobić (FYI, mogę zrobić to zapytanie na CoreData podkład SQLite DB):
SELECT ZDAYSTRING FROM ZPERSISTEDDAY GROUP BY ZDAYSTRING HAVING COUNT(ZDAYSTRING) > 1;
ta zwraca tylko dayStrings które mają duplikaty i możesz następnie uzyskać wszystkie pola dla tych obiektów, wysyłając zapytanie za pomocą wynikowych łańcuchów dni (możesz użyć go jako sub-zapytania, aby zrobić to wszystko w jednym żądaniu).
Wygląda na to, że NSFetchRequest zawiera wszystkie wymagane elementy, ale wydaje się, że nie działa. Oto, co próbowałem zrobić:
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: @"[email protected] > 1"];
request.resultType = NSDictionaryResultType;
NSArray *results = [context executeFetchRequest:request error:NULL];
To nie działa. :-P Jeśli spróbuję, otrzymam komunikat "Nieobsługiwana liczba wyrażeń funkcji: (dayString)" podczas próby pobrania. Nie sądzę, że dayString w "dayString. @ Count" ma nawet znaczenie w powyższym kodzie ... ale wstawiłem to dla jasności (liczba SQL działa na zgrupowanych wierszach).
Moje pytanie brzmi: czy to możliwe, a jeśli tak, to jaka jest składnia, aby to zrobić? Nie mogłem znaleźć niczego w dokumentach CoreData, aby wskazać, jak to zrobić.
Znalazłem jeden podobny wpis SO, którego teraz niestety nie mogę znaleźć, który dotyczył liczenia w klauzuli posiadania (nie sądzę, żeby była grupa). Ale plakat porzucił i zrobił to inaczej, nie znajdując rozwiązania. Mam nadzieję, że jest to bardziej jednoznaczne, więc może ktoś ma odpowiedź. :)
Dla porównania, jest to, co robię teraz, że nie działa, ale wymaga powrocie prawie wszystkie wiersze, ponieważ istnieje bardzo niewiele duplikaty w większości przypadków:
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];
Mam następnie do pętli nad wynikiem i zwracają tylko wyniki, które mają dayStringCount> 1. Jaka powinna być klauzula mająca. :-P
UWAGA: Wiem, że CoreData nie jest SQL. :) Chciałbym tylko wiedzieć, czy mogę wykonać równoważny typ operacji z taką samą wydajnością jak SQL.
Zgaduję odpowiedź ma coś wspólnego z użyciem podzapytania w NSPredicate. Czy próbowałeś tego? –
Spójrz na http://www.atomicbird.com/blog/icloud-complications-part-2, wydaje się, że w to włożyłeś trochę uwagi :) –
Nie jestem pewien, jak podzapytanie mi tu pomoże. Chyba żebym mógł wykonać podzapytanie, które zrobiło grupę, z klauzulą mającą w sobie licznik. ;-) Można również wykonać sprzężenie z tą samą tabelą, aby wykryć duplikaty, ale nie jestem też pewny, jak by to zrobić z danymi podstawowymi. Odnośnie tej strony, zapobiegając oszustwom, które znam. Problem polega na oczyszczeniu istniejących duplikatów. Wygląda na to, że jego rozwiązaniem było zrobienie tego, co zrobiłem powyżej (uwzględnij liczbę w wynikach zapytania). To wciąż śmierdzi, ponieważ przyniesie wiele wyników, jeśli stół będzie duży. Dzięki! – stuckj