Swift, CoreData, FetchRequest, 2个实体, ManyToMany, with GroupBy, Having Count and Sort, How?

问题描述 投票:0回答:1

我对CoreData请求很不满意。用一些SQL派生的方法,我就能搞定。但在这里我需要一些帮助。

我有两个实体,有manyToMany关系。它看起来像这样。

Repeatable (name: String, type: Int16, entries: [Entry])
Entry      (id: UUID, createdAt: Date, repeatables: [Repeatable])

我想得到一个重复数据的列表,它属于一个以上的条目,按关联数排序

在SQL中,它看起来像这样。

SELECT rep.Z_PK, COUNT(rep.Z_PK) as count FROM ZREPEATABLE AS rep
INNER JOIN Z_1REPEATABLES as link
ON rep.Z_PK = link.Z_2REPEATABLES
INNER JOIN ZENTRY AS entry
ON entry.Z_PK = link.Z_1ENTRIES
GROUP BY rep.Z_PK
HAVING count > 1
ORDER BY count DESC

我可以在swift中用核心数据做这个吗? 代码是怎样的?

编辑:我想出了这样一个办法(部分解决方案):我可以在swift中用Core Data做这个事情吗?

我想到了这个(部分解决方案)。

let somethingED = NSExpressionDescription()
somethingED.expression = NSExpression(forKeyPath: "[email protected]")
somethingED.name = "countSth"
somethingED.expressionResultType = .integer64AttributeType

let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Repeatable")
fetchRequest.propertiesToFetch = ["name", somethingED]
fetchRequest.relationshipKeyPathsForPrefetching = ["entries"]
fetchRequest.resultType = .dictionaryResultType
fetchRequest.predicate = NSPredicate(format: "$countSth > 1")

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext

do {
    let result = try context.fetch(fetchRequest)
    print(result)
} catch{
    print("error fetching: \(error)")
}

这个解决方案的问题是... 我不知道如何排序。我总是以一个错误结束。而且这也不是group-by+有构造。所以,我想,好吧,如果这能行,我不需要group-by。但我还是想知道如何或者是否可以用group-by + having谓词?


编辑2:

所以在评论里 @pbasdf 链接了这个从WWDC 2019 (+1)。它完全描述了我的用例,并提供了一个完美的解决方案... ... 但是......它是针对iOS 13的,但我也想支持iOS 12(比如iPhone 6)。所以我最终想出了这个解决方案:有了一个 entriesCount 属性+在每次保存时更新该值.现在保存会慢一点,但读取会超快,因为在查询中不需要表连接、分组或计数。

    public override func willSave() {
        let newValue =  Int16(self.entries?.count ?? 0)
        if countEntries != newValue, changedValues()[#keyPath(Repeatable.countEntries)] == nil, !isDeleted {
            countEntries = newValue
        }
        super.willSave()
    }
swift core-data group-by many-to-many nsfetchrequest
1个回答
1
投票

是的,你可以这样做。你可以创建一个 NSFetchRequest 并定制其 sortDescriptorspredicate 属性来获得你想要的结果。

如果你正确设置了你的核心数据关系,就不需要手动指定 "内部连接 "之类的东西。你只需在数据模型中设置多对多的关系,然后就可以在你的谓词中直接访问这些关系。

我不知道你的整个查询是否完全可以翻译成一次取数,但没有必要限制自己。一旦你完成了你的fetch,你可以在一个管理对象上下文中做进一步的refinementprocessing。这就是CoreData ORM的全部意义,你只需要直接在对象上工作,而不用担心底层DB。

© www.soinside.com 2019 - 2024. All rights reserved.