使用BETWEEN在Realm中查找对象

时间:2017-05-31 18:10:20

标签: swift3 realm

我正在使用如下所示的Realm对象并创建了对象的数据库。我还创建了一个函数来根据当前时间查找元素。我在创建此函数所需的谓词时遇到困难。我正在使用Realm备忘单中定义的格式,但我得到如下例外:

  

由于未捕获的异常“无效的谓词”而终止应用,原因:   '使用BETWEEN运算符的谓词必须将KeyPath与a进行比较   聚合有两个值'

import Foundation
import RealmSwift

func composeUniqueRealmPrimaryKeyForWorkorder(_ start:String) -> String {
    return start
}

class WorkorderRecord: Object {

    dynamic var id = ""
    dynamic var workorder = ""
    dynamic var start = "" // defines start time string as in 2017-06-09 9:00
    dynamic var end = "" // defines end of interval as in 2017-06-10 16:30


    override static func primaryKey() -> String? {
        return "id"
    }

    override class func indexedProperties() -> [String] {
        return ["workorder","start","end"]
    }

    convenience init(_ workorder:String, start:String, end:String) {
        self.init()
        self.id = composeUniqueRealmPrimaryKeyForWorkorder (workorder)
        self.workorder = workorder
        self.start = start
        self.end = end
    }
}

func getValueForInterval(time:String) -> String? {
    let realm = try! Realm()
    let predicate = NSPredicate(format: "%@ BETWEEN {start , end }", time)
    let r = realm.objects(WorkorderRecord.self).filter(predicate)
    if r.count == 0 {
        print("NO RECORD FOUND")
        return ""
    } else {
        let workorder = r[0].workorder
        let start = r[0].start
        let end = r[0].end
        print("RECORD Retrieved: workorder= \(workorder) start= \(start) end= \(end)")
        return workorder
    }
}

1 个答案:

答案 0 :(得分:2)

如果您推断BETWEEN运算符提供的语义,您很快就会发现foo BETWEEN {bar, baz}等同于foo >= bar AND foo <= baz [0]。虽然Realm目前仅支持{bar, baz}聚合表达式中的常量值,但对正常的关系比较运算符没有这样的限制。

您将遇到的一个问题是,虽然Realm支持数字和>=类型的<=Date等比较运算符,但字符串类型目前不支持它们。由于您将开始和结束时间存储为字符串,因此无法在不进行进一步更改的情况下利用此转换。

如果您使用Date类型切换到存储时间,则可以将查询重新表述为:

let predicate = NSPredicate(format: "%@ >= start AND %@ <= end", time, time)

这样做还可以减少存储日期所需的空间。

[0]:请注意,仅当密钥路径foo不遍历任何多对多关系时才会出现这种情况。如果它确实遍历多个关系,则需要SUBQUERY来匹配BETWEEN的语义。