核心数据查询,每年最近的汽车?

Posted

技术标签:

【中文标题】核心数据查询,每年最近的汽车?【英文标题】:Core Data Query, most recent car per year? 【发布时间】:2017-11-16 03:03:28 【问题描述】:

在我的模型中,我有一个 Car 实体。

汽车 年 创建日期 名字

我想运行一个 fetch 来返回每年所有最近的汽车,其中 name 不是 nil(name 可以是 nil)。

因此,如果我有 3 辆 2000 年的汽车和 5 辆 2010 年的汽车,我想从获取请求中总共获得 2 辆汽车(最近的是 2000 年,最近的是 2010 年)。

我不确定如何编写正确的谓词来实现这一点。我查看了 returnDistinctResults 选项,但我不确定这是正确的路径,它还说它只适用于对我不起作用的 NSDictionaryResultType。

完成这项工作的正确查询/谓词是什么?

【问题讨论】:

【参考方案1】:

您最好使用算法简单地遍历每条记录。

允许您的 Car 类,定义以下内容。

struct C 
    var year: Int
    var created: Date
    var name: String?


var cars = [C(year: 2009, created: Date(), name: nil), C(year: 2009, created: Date(), name: "Green"), C(year: 2010, created: Date(), name: "Green"), C(year: 2010, created: Date(), name: "Orange"), C(year: 2010, created: Date(), name: "Orange")]

var carsPerYear = [Int: [String: Int]]()

for car in cars 
    if let name = car.name 
        var info: [String: Int]? = nil
        if carsPerYear.keys.contains(car.year) 
            info = carsPerYear[car.year]
         else 
            info  = [String: Int]()
        
        if !info!.keys.contains(name) 
            info![name] = 0
        
        info![name] = info![name]! + 1
        carsPerYear[car.year] = info
    


for year in carsPerYear.keys 
    let info = carsPerYear[year]!
    let sorted = info.keys.sorted info[$0]! > info[$1]! 
    print(year, sorted.first!)

给出输出

2009 Green 
2010 Orange

有时SQL或CoreData不能轻易解决问题,最好只写排序算法。

【讨论】:

【参考方案2】:

您可以实现这一点,假设您将一个年份数组传递给一个算法,并期望以字典的形式得到一个结果,每一年您作为一个对象的键传入,该对象对应于最那年最近的车。

即:

let years : [Int] = [2000, 2005]


//The ideal method:

func mostRecentFor<T>(years: [Int]) -> [String:T]

假设您只使用少量搜索年份,并且您的数据库中有少量汽车,您不必担心线程问题。否则,对于这种方法,您必须使用并发或专用线程进行提取以避免阻塞主线程。出于测试目的,您不需要这样做。

要做到这一点,您可以使用以下方法。

首先,应该像其他答案所建议的那样在年份上使用数字谓词。 为此,您将使用 NSPredicate 的日期格式:

NSPredicate(format: "date == %@", year)

因此,您的模型应该将年份作为参数,将实际的 nsdate 作为另一个参数。然后,您将使用设置为 1 的 fecthLimit 参数,并将 sortDescriptor 应用于 nsDate 键参数。后两者的组合将确保只返回给定年份的最年轻或最旧的值。

func mostRecentFor(years: [Int]) -> [String:Car] 
        let result : [String:Car] = [:]
        for year in years 
           let request: NSFetchRequest<CarModel> = CarModel.fetchRequest()
           request.predicate = NSPredicate(format: "date == %@ AND name != nil", year)
           request.fetchLimit = 1
           let NSDateDescriptor: let sectionSortDescriptor = NSSortDescriptor(key: "nsDate", ascending: true)
           let descriptors = [NSDateDescriptor]
           fetchRequest.sortDescriptors = descriptors
           do 
                let fetched = try self.managedObjectContext.fetch(request) as 
                [CarModel]
                guard !fetched.isEmpty, fetched.count == 1 else 
                    print("No Car For year: \(year)")
                    return
                
                result["\(year)"] = new[0].resultingCarStruct //custom parameter here.. see bellow
             catch let err 
                print("Error for Year: \(year), \(err.localizedDescription)")
            
        
        return result

我们在这里使用升序设置为true,因为我们希望第一个值,即由于fetchLimit值为1而实际返回的值,是该年份最早的汽车,或者是最小的汽车nsDate 键的时间戳

这应该为您提供一个用于小型数据存储和测试的简单获取查询。此外,创建一个方法或参数来将 CarModel 解释为其对应的 Car 结构体可以更简单地从 CD 转到内存对象。

所以你会像这样搜索你的汽车:

let years = [1985, 1999, 2005]
let cars = mostRecentFor(years: years)

// cars = ["1985": Car<year: 1985, name: "Chevrolet", nsDate: "April 5th 1985">, "1999" : Car<year: 1999, name: "Toyota Corolla", nsDate: "February 5th 1999">]
// This examples suggests that no cars were found for 2005

【讨论】:

我明白你的意思,这有三个问题: 1. 这种方法需要大量的磁盘,非常非常慢。 2.这个问题不是要求通过一系列年份,我只是想要每年最近的汽车 3.这个答案没有考虑名称!= nil 条件。谢谢。 1:我指定此方法适用于测试/小型数据库,并且您需要将其调整为并发包装器以获取更多信息。 2:“每年”可以表示从一组年份到两个给定年份之间的每一年的任何内容,这至少会导致一个年份数组(或在这种情况下为整数)。 3:确实我忘记了名字,检查 nil 是通过在谓词字符串中添加一个 AND 运算符来完成的,然后在字符串中或使用参数符号添加该避免的值。生病更新 这没有提供问题所要求的答案。对不起。 您的问题是询问查询中指定的每年最早的汽车,其名称没有零? “核心数据查询”,而不是“核心数据查询”。一个查询得到我想要的。您提供的内容在我可能传入的每一年都会进入磁盘。另外,正如我上面所说,我没有指定我想在几年内传递。那是您在此处添加的内容...所以,再次抱歉,但您的回答并未解决问题。谢谢

以上是关于核心数据查询,每年最近的汽车?的主要内容,如果未能解决你的问题,请参考以下文章

核心数据父子UITableView关系

试图掌握核心数据中的关系

将子实体加载到核心数据中的托管对象

iPhone核心数据-简单查询

XCode - 删除核心数据中的相关对象

库克不愿量产每年投 10 亿,已耗时 8 年的苹果汽车何时能面世?