2015-01-25 1 views
5

Ich habe eine Tabelle in Core Data mit den folgenden Eigenschaften:Gruppe durch eine Eigenschaft, während mehr mit Kern Abrufen von Daten

date, name, phone 

ich mit Namen nach Datum geordnet eine Liste von 5 eindeutigen Telefonnummern abrufen möge. So in MySQL wäre es so etwas wie:

SELECT name, phone FROM myTable GROUP BY phone ORDER BY date 

Also, wenn ich diese Liste von Daten:

01/23/2015 someName1 12345678 
01/21/2015 someName2 12345678 
01/21/2015 someOtherName1 987654321 

Ich möchte eine Liste der eindeutigen Telefonnummern mit dem Datumsfeld Controlling abzurufen, welcher Name mit irgendwelchen doppelten Nummern verbunden sein. In diesem Fall wäre das gewünschte Ergebnis:

01/23/2015 someName1 12345678 
01/21/2015 someOtherName1 987654321 

aber dies zu tun mit einem NSFetchRequest scheint ein wenig, da die setPropertiesToGroupBy kompliziert erfordert die gleiche Liste von Eigenschaften enthält, wie in setPropertiesToFetch definiert.

Mit anderen Worten, das ist, wie ich denke, dass ich es zu tun wäre in der Lage:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"someEntity" inManagedObjectContext:someContext]; 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setEntity:entity]; 
    [request setResultType:NSDictionaryResultType]; 

    [request setPropertiesToFetch:@[@"name", @"phone"]]; 
    [request setPropertiesToGroupBy:@[@"phone"]]; 
    [request setFetchLimit:5]; 

    NSSortDescriptor *sortByCreatedDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]; 
    [request setSortDescriptors:@[sortByCreatedDate]]; 

Allerdings werde ich auf der propertiesToGroupBy eine Ausnahme erhalten, wenn ich das name Feld als auch enthalten.

Wie kann ich erreichen, was ich will, ohne manuell durch die Liste gehen zu müssen?

+0

Bitte können Sie Ihre Frage bearbeiten, um ein Beispiel Ihrer Daten und Ihre gewünschte Ausgabe aufzunehmen? Von Ihrer Beschreibung bin ich mir nicht sicher, ob Sie "Gruppieren nach" verwenden müssen. – pbasdf

+0

@pbasdf natürlich - siehe meine aktualisierte Frage. Lassen Sie mich wissen, wenn Sie weitere Fragen haben. –

+0

hast du es versucht? NSArray * groups = [fetchedObjects valueForKeyPath: @ "@ distinctUnionOfObjects.phone"]; – Jim

Antwort

4

Mit einer Maßgabe, dass ich denke dies funktioniert; Ich überlasse es Ihnen, es zu Tode zu testen:

Sie keine anderen Attribute propertiesToFetch, über die in der propertiesToGroupBy hinzufügen können, aber es scheint, können Sie die objectID in den Eigenschaften gehören zu holen. Um dies zu tun, bauen ein NSExpression und zugehörige NSExpressionDescription für das „bewertet Objekt“:

NSExpression *selfExp = [NSExpression expressionForEvaluatedObject]; 
NSExpressionDescription *selfED = [[NSExpressionDescription alloc] init]; 
selfED.name = @"objID"; 
selfED.expression = selfExp; 
selfED.expressionResultType = NSObjectIDAttributeType; 

nun einen weiteren Ausdruck/Beschreibung definieren, um die max (Datum) zu erhalten:

NSExpression *maxDate = [NSExpression expressionForKeyPath:@"date"]; 
NSExpression *indexExp = [NSExpression expressionForFunction:@"max:" arguments:@[maxDate]]; 
NSExpressionDescription *maxED = [[NSExpressionDescription alloc] init]; 
maxED.name = @"maxDate"; 
maxED.expression = indexExp; 
maxED.expressionResultType = NSDateAttributeType; 

Dann sind diese beiden Ausdruck Beschreibungen in der Liste der Eigenschaften zu holen:

[request setPropertiesToFetch:@[@"phone", maxED, selfED]]; 
[request setPropertiesToGroupBy:@[@"phone"]]; 

Wenn Sie den Abruf laufen, jedes Element in dem resultierenden Array einen Schlüssel hat „OBJID“ conta die Objekt-ID für das relevante Objekt eingeben. Sie können das, entpacken Sie den Namen für den Zugriff auf Telefon, etc., mit etwas in dieser Richtung:

NSArray *results = [self.context executeFetchRequest:request error:&error]; 
for (NSDictionary *dict in results) { 
    NSDate *maxDate = dict[@"maxDate"]; 
    NSString *phone = dict[@"phone"]; 
    NSManagedObjectID *objID = [dict valueForKey:@"objID"]; 
    NSManagedObject *object = [self.context objectWithID:objID]; 
    NSString *name = [object valueForKey:@"name"]; 
} 

Ein besonderer Aspekt ich bin nicht sicher ist, wie diese sich verhalten, wenn zwei Reihen haben genau die gleiche date.

+0

Ich nehme an, es sollte sagen: maxED.expression = maxDate ;? Bei der Verwendung dieses Ansatzes bekomme ich diese Ausnahme: 'NSInvalidArgumentException', Grund: 'SELECT-Klauseln in Abfragen mit GROUP BY-Komponenten können nur Eigenschaften enthalten, die in GROUP BY oder Aggregatfunktionen benannt sind (Datum ist nicht in der GROUP BY)' –

+0

Es tut uns leid Ich habe beim Schneiden/Einfügen eine Schlüsselzeile verpasst. Ich werde die Antwort aktualisieren .... – pbasdf

+0

@ SteffenD.Sommer Ich habe die Zeile hinzugefügt: NSExpression * indexExp = [NSExpression expressionForFunction: @ "Max:" Argumente: @ [maxDate]]; in der Antwort oben. – pbasdf

Verwandte Themen