Reputation: 2918
I am using Realm object as shown below and created a database of the objects. I also created a function to find an element based on current time. I am having difficulty in creating the predicate this function needs. I am using a format as defined in the Realm cheatsheet, but I'm getting an exception as follows:
Terminating app due to uncaught exception 'Invalid predicate', reason: 'Predicate with BETWEEN operator must compare a KeyPath with an aggregate with two values'
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
}
}
Upvotes: 2
Views: 1684
Reputation: 18308
If you reason about what semantics the BETWEEN
operator provides, you'll soon realize that foo BETWEEN {bar, baz}
is equivalent to foo >= bar AND foo <= baz
[0]. While Realm currently supports only constant values in the {bar, baz}
aggregate expression, there's no such restriction on normal relational comparison operators.
One sticking point you'll run into is that while Realm supports comparison operators such as >=
and <=
on numeric and Date
types, they are not currently supported on string types. Since you're storing your start and end times as strings, you're not able to take advantage of this transformation without further changes.
If you switch to storing your times using the Date
type, you'll be able to reformulate your query as:
let predicate = NSPredicate(format: "%@ >= start AND %@ <= end", time, time)
This would also have the advantage of reducing the space required to store the dates.
[0]: Note that this is only true if the key path foo
does not traverse any to-many relationships. If it does traverse to-many relationships, a SUBQUERY
is needed to match BETWEEN
s semantics.
Upvotes: 4