NSFetchRequest:查询不同的值并计算其他属性值
NSFetchRequest: Query for distinct values and count other properties values
我尝试为具有 country
和 city
:
等属性的实体 Location
设置一个 NSFetchRequest
country | city
————————————————
Germany | Berlin
USA | San Francisco
USA | New York
Germany | Munich
Germany | Munich
USA | San Francisco
Germany | Stuttgart
NSFetchRequest
应该 return 国家(或具有适当国家的 Location 对象)和城市数量。
[
{ country: 'Germany', cityCount: 3 },
{ country: 'USA', cityCount: 2 }
]
我知道我可以只获取所有条目 'count it myself' 但我对如何设置适当的获取请求很感兴趣(或者如果可能的话)并且想看看你会怎么做做吧! :)
为了实现(我认为)您想要的,我不得不求助于两个单独的获取。第一次提取为 country
和 city
的每个不同组合获取一个对象的 objectID。第二次提取使用 IN
谓词过滤到这些对象。它使用 NSExpression
和 propertiesToGroupBy
来获取每个 country
:
的计数
// 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 谓词会减慢速度。您可能会发现获取所有内容并计算它们的效率更高。
此问题的正确答案是重构数据模型以避免冗余。
国家/地区字符串在 table 中不必要地重复。此外,您使一个简单的查询无缘无故地变得复杂。该模型应该反映您的数据,并且为每个美国城市写出 "USA" 既不聪明也不高效。
您的数据模型应如下所示
Country <----->> City
现在你可以只获取所有国家和城市cities.count
。
我尝试为具有 country
和 city
:
Location
设置一个 NSFetchRequest
country | city
————————————————
Germany | Berlin
USA | San Francisco
USA | New York
Germany | Munich
Germany | Munich
USA | San Francisco
Germany | Stuttgart
NSFetchRequest
应该 return 国家(或具有适当国家的 Location 对象)和城市数量。
[
{ country: 'Germany', cityCount: 3 },
{ country: 'USA', cityCount: 2 }
]
我知道我可以只获取所有条目 'count it myself' 但我对如何设置适当的获取请求很感兴趣(或者如果可能的话)并且想看看你会怎么做做吧! :)
为了实现(我认为)您想要的,我不得不求助于两个单独的获取。第一次提取为 country
和 city
的每个不同组合获取一个对象的 objectID。第二次提取使用 IN
谓词过滤到这些对象。它使用 NSExpression
和 propertiesToGroupBy
来获取每个 country
:
// 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 谓词会减慢速度。您可能会发现获取所有内容并计算它们的效率更高。
此问题的正确答案是重构数据模型以避免冗余。
国家/地区字符串在 table 中不必要地重复。此外,您使一个简单的查询无缘无故地变得复杂。该模型应该反映您的数据,并且为每个美国城市写出 "USA" 既不聪明也不高效。
您的数据模型应如下所示
Country <----->> City
现在你可以只获取所有国家和城市cities.count
。