2016-01-05 1 views
8

J'ai un projet dans lequel je dois effectuer une requête d'extraction qui obtient la date de mise à jour la plus récente d'une entité de base de données. Quand j'examine réellement les résultats retournés par ma requête cependant je vois un comportement plutôt étrange. En plus du résultat «correct» contenant la date, les résultats incluent également un élément de dictionnaire vide. Cela arrive à chaque fois, indépendamment de ce à quoi ressemblent les données sous-jacentes. Encore plus étrange, si j'active sql en me connectant dans xcode et que j'exécute la requête journalisée sur la sqllite db, elle produit le résultat correct sans aucune entrée supplémentaire. Je ne suis pas sûr de ce que je fais mal ici, toute aide serait appréciée.Demande d'extraction rapide Renvoyer l'élément vide dans les résultats

La fonction qui construit et exécute la requête:

func queryForContactDate(context:NSManagedObjectContext) -> AnyObject? 
{ 

    var expressionDescriptions = [AnyObject](); 

    let expressionDescription = NSExpressionDescription() 

    // Name the column 
    expressionDescription.name = "maxUpdated" 
    // Use an expression to specify what aggregate action we want to take and 
    // on which column. In this case max on the update_at column 
    expressionDescription.expression = NSExpression(format: "@max.updated_at") 
    // Specify the return type we expect 
    expressionDescription.expressionResultType = .DateAttributeType 
    // Append the description to our array 
    expressionDescriptions.append(expressionDescription) 

    // Build out our fetch request the usual way 
    let request = NSFetchRequest(entityName: Contact.entityName()) 

    // Specify we want dictionaries to be returned 
    request.resultType = .DictionaryResultType 

    // Hand off our expression descriptions to the propertiesToFetch field. 
    request.propertiesToFetch = expressionDescriptions 

    // Our result is going to be an array of dictionaries. 
    var results:[[String:AnyObject]]? 

    // Perform the fetch. This is using Swfit 2, so we need a do/try/catch 
    do { 
     results = try context.executeFetchRequest(request) as? [[String:AnyObject]] 
    } catch _ { 
     // If it fails, ensure the array is nil 
     results = nil 
    } 

    return results![0]; 
} 

Si je mets un point d'arrêt à la fin et imprimer les résultats qu'il produit:

Printing description of results: 
▿ Optional([[:], ["maxUpdated": 2015-12-30 20:05:31 +0000]]) 
    ▿ Some : 2 elements 
    - [0] : 0 elements 
    ▿ [1] : 1 elements 
     ▿ [0] : 2 elements 
     - .0 : "maxUpdated" 
     - .1 : 2015-12-30 20:05:31 +0000 
+0

Pouvez-vous imprimer avec context.executeFetchRequest (request) est sans cast? Il est possible que vous lanciez quelque chose qui n'est pas réellement [[String: AnyObject]]. Surtout dans les coins de l'API qui sont portés à Swift, il y a des choses étranges qui continuent avec les dictionnaires/tableaux – tbondwilkinson

+0

Je pense que vous êtes sur la bonne voie mais l'impression n'était pas particulièrement éclairante. Voici ce que j'ai obtenu: [{ }, { maxUpdated = "2015-12-30 20:05:31 +0000"; }] – pbuchheit

+0

Ensuite, je voudrais mettre un point d'arrêt dans la méthode de récupération et retracer et voir où la demande provient/quand ce dictionnaire vide y arrive – tbondwilkinson

Répondre

1

La manière traditionnelle de base de données pour obtenir un élément max ou min est à interroger avec une limite de récupération de 1 et un tri sur cette clé. Comme dans ce code Objective-C:

+ (NSFetchRequest *) requestForStatusWithMaxID { 

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: kAMStatusEntity]; 

    NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey: kAMTwID ascending:NO]; 

    request.sortDescriptors = @[sd]; 
    request.fetchLimit = 1; 

    return request; 

} // +requestForStatusWithMaxID 

Il serait assez simple de modifier ci-dessus pour votre propriété updated_at.

+0

Oui, il est possible d'effectuer le chargement de cette façon, mais les performances vont en souffrir à mesure que la taille de la table sous-jacente augmente. En outre, je vois ce même comportement si j'essaie d'autres fonctions d'agrégat comme SUM. Il suffit de trier et de prendre le premier résultat n'aidera pas avec ceux-ci. – pbuchheit

+0

Toute requête sans index, y compris la vôtre répertoriée ci-dessus, a des problèmes de mise à l'échelle à mesure que la table se développe. Quelle est la taille de votre table? 100, 1 000, 10 000, 1 M lignes? Si elle est grande, vous avez besoin d'un index - pour les deux styles de requête. – adonoho