Core data NSFetchRequest:查询不同的值并计算其他属性值

Core data NSFetchRequest:查询不同的值并计算其他属性值,core-data,nspredicate,nsfetchrequest,nsexpression,Core Data,Nspredicate,Nsfetchrequest,Nsexpression,我尝试为实体位置设置一个NSFetchRequest,属性为国家和城市: country | city ———————————————— Germany | Berlin USA | San Francisco USA | New York Germany | Munich Germany | Munich USA | San Francisco Germany | Stuttgart NSFetchRequest应返回国家(或具有相应国家/地区的位置对

我尝试为实体
位置
设置一个
NSFetchRequest
,属性为
国家
城市

country  | city
————————————————
Germany  | Berlin
USA      | San Francisco
USA      | New York
Germany  | Munich
Germany  | Munich
USA      | San Francisco
Germany  | Stuttgart
NSFetchRequest
应返回国家(或具有相应国家/地区的位置对象)和城市数

[
    { country: 'Germany', cityCount: 3 },
    { country: 'USA', cityCount: 2 }
]

我知道我可以获取所有条目并“自己计数”,但我对如何设置适当的获取请求(或者如果可能的话)感兴趣,并想看看您将如何做!)

为了实现(我想)你想要的东西,我不得不采取两种不同的方法。第一次获取为
国家
城市
的每个不同组合获取一个对象的objectid。使用谓词中的过滤第二次提取,仅过滤这些对象。它使用
NSExpression
propertiesToGroupBy
获取每个
国家/地区的计数:

    // Step 1, get the object IDs for one object for each distinct country and city 
    var objIDExp = NSExpression(expressionType: NSExpressionType.EvaluatedObjectExpressionType)
    var objIDED = NSExpressionDescription()
    objIDED.expression = objIDExp
    objIDED.expressionResultType = .ObjectIDAttributeType
    objIDED.name = "objID"
    var fetch = NSFetchRequest(entityName: "Location")
    fetch.propertiesToFetch = [objIDED]
    fetch.propertiesToGroupBy = ["country", "city"]
    fetch.resultType = .DictionaryResultType
    let results = self.managedObjectContext!.executeFetchRequest(fetch, error: nil)

    // extract the objectIDs into an array...
    let objIDArray = (results! as NSArray).valueForKey("objID") as! [NSManagedObjectID];

    // Step 2, count using GROUP BY
    var countExp = NSExpression(format: "count:(SELF)")
    var countED = NSExpressionDescription()
    countED.expression = countExp
    countED.expressionResultType = .ObjectIDAttributeType
    countED.name = "count"
    var newFetch = NSFetchRequest(entityName: "Location")
    newFetch.predicate = NSPredicate(format: "SELF IN %@", objIDArray)
    newFetch.propertiesToFetch = ["country", countED]
    newFetch.propertiesToGroupBy = ["country"]
    newFetch.resultType = .DictionaryResultType
    let newResults = self.managedObjectContext!.executeFetchRequest(newFetch, error: nil)
    println("\(newResults!)")

这将是低效的:如果您有大量不同的国家和城市,IN谓词将减慢速度。您可能会发现提取所有数据并对其进行计数更有效。

这个问题的正确答案是重构数据模型,以避免冗余

表中不必要地重复了国家/地区字符串。此外,您还可以进行一个简单的查询,而查询的复杂性是无缘无故的。模型应该反映你的数据,为每个美国城市写上“USA”是不明智的,也没有效率的

您的数据模型应该如下所示

Country <----->> City
国家>城市

现在,您只需获取所有国家/地区,并获取具有
城市的城市。count

这当然是可能的。您使用的是Swift还是Objective-C?我使用的是Swift,而不是Obj-C,但两者我都能读;)我说得太快了;在使用“分组方式”进行计数的同时,实现“独特”要求并不容易。也许这就是你问的原因。我以前从未使用过IN谓词,这确实是一种非常酷的方法。我希望它能在一个月内实现。如果下周没有其他解决方案,我会接受你的回答!非常感谢您的支持!:)这个解决方案比使用KVC在内存中获取和解析更长,效率更低。。。但有时你没有这个机会;)