我正在尝试构建一个会计应用程序,其中可以有很多帐户,每个帐户可以有很多条目。每个条目都有日期和金额。
条目链接到 Account 类,如下所示:
let entries = LinkingObjects(fromType: Entry.self, property: "account").sorted(byKeyPath: #keyPath(Entry.date))
我想按帐户名称分组,得到任何给定日期之间每个月的金额总和。出于报告目的,日期可能会有所不同。
Realm 没有 groupby 函数,我无法轻松获得列为帐户名称、总计、平均值、sumOf(month1)、sumOf(month2) 等的结果
因此;我需要用代码来做,但结果很慢。我的代码中是否缺少任何可以显着提高计算速度的特定 Realm ?
此代码正在为每个帐户和每个时期运行(对于年度报告,这意味着每个帐户运行 12 次)以及运行缓慢的原因:
let total: Double = realm
.objects(Entry.self)
.filter("_account.fullPath == %@", account.fullPath)
.filter("date >= %@ AND date <= %@", period.startDate, period.endDate)
.filter("isConsolidation != TRUE")
.sum(ofProperty: "scaledAmount")
下面是完整的代码,我必须循环每个帐户并为每个期间运行查询:
private func getMonthlyValues(for accounts: [Account], in realm: Realm, maxLevel: Int) -> String {
guard accounts.count > 0 else { return "" }
guard accounts[0].displayLevel < maxLevel else { return "" }
var rows: String = ""
for account in accounts.sorted(by: { $0.fullPath < $1.fullPath }) {
if account.isFolder {
let row = [account.localizedName.htmlColumn].htmlRow
rows += row
rows += monthlyValues(for: Array(account.children), in: realm, maxLevel: maxLevel)
} else {
var row: [String] = []
var totals: [Double] = []
// period has a start date and an end date
// monthlyPeriods returns the period in months
// for a datePeriod starting February 10, and ending in November 20 (for whatever reason)
// monthlyPeriods returns 10 periods for each month starting from [February 10 - February 28],
// and ending [November 1 - November 20]
// below gets the some for the given period for the current account
// for this example it runs 10 times for each account getting the sum for each period
for period in datePeriod.monthlyPeriods {
let total: Double = realm
.objects(Entry.self)
.filter("_account.fullPath == %@", account.fullPath)
.filter("date >= %@ AND date <= %@", period.startDate, period.endDate)
.filter("isConsolidation != TRUE")
.sum(ofProperty: "scaledAmount")
totals.append(total)
}
let total = totals.reduce(0, +)
guard total > 0 else { continue }
let average = AccountingDouble(total / Double(totals.count)).value
row.append("\(account.localizedName.htmlColumn)")
row.append("\(total.htmlFormatted().htmlColumn)")
row.append("\(average.htmlFormatted().htmlColumn)")
row.append(contentsOf: totals.map { $0.htmlFormatted().htmlColumn })
rows += row.htmlRow
}
}
return rows
}
非常感谢任何帮助。
最佳答案
由于您没有使用 Results 的自动更新属性,我尝试的不是每个月运行不同的查询,而是使用单个查询获取所有条目,然后使用 Swift 的内置 进行过滤和求和filter
和 reduce
函数,这样你可以减少 Realm 查询的开销。
只需让 let entries = realm.objects(Entry.self)
使用单个查询存储所有条目,然后您可以使用 Array(entries).filter({$0 .account.fullPath == account.fullPath})
等。对于每个帐户和日期,这不会在您每次进行计算时查询 Realm。如果您的条目不会在计算之间发生变化,您甚至可以使用 let entries = Array(realm.objects(Entry.self))
关于swift - 由于 Realm [iOS] 中缺少 GroupBy 和 Sum,操作非常缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45939684/