Realmswift + Multiple Predicate

RealmSwift + Multiple Predicate

You shouldn't dynamically craft an NSPredicate query string. It's much easier (and safer) to create an NSCompoundPredicate programmatically. You can pass NSPredicates to Realm's RealmCollectionType.filter(...) method. Here's an example to get all Persons who have either an Xbox or a Playstation 4:

// could use .AndPredicateType here too, depending on what you want
let query = NSCompoundPredicate(type: .OrPredicateType, subpredicates: [NSPredicate(format: "console = 'Xbox'"), NSPredicate(format: "console = 'Playstation 4')])
let player = realm.objects(Person).filter(query)

Although in your case, you might be better off using an IN query if you want OR semantics:

let selectedConsoles = ["Xbox", "Playstation 4"]
let player = realm.objects(Person).filter("console IN %@", selectedConsoles)

Query several fields containing a list of string values (Realm Swift)

I suggest using NSCompoundPredicate against hand crafting predicate strings. With an NSCompoundPredicate you can potentially string together multiple or or as a.masri rightly calls out, in predicates to form a single predicate that you can then pass to realm.

Filter querying multiple objects from Realm using List of Primary Keys

I think you are asking how to query Realm for items that have keys that match a set of keys in an array.

So given a DogClass Realm Object

class DogClass: Object {
@objc dynamic var dog_id = NSUUID().uuidString
@objc dynamic var dog_name = ""

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

and suppose we know we want to retrieve three dogs that match some given primary keys

let keysToMatch = ["302AC133-3980-41F3-95E8-D3E7F639B769", "54ECC485-4910-44E5-98B9-0712BB99783E", "71FE403B-30CD-4E6C-B88A-D6FDBB08C509"]
let dogResults = realm.objects(DogClass.self).filter("dog_id IN %@", keysToMatch)
for dog in dogResults {
print(dog.dog_id, dog.dog_name)
}

Note the use of IN in the filter, which will match any dogs with id's in the given array.

You can also pass in a Realm List Object instead of a Swift array and get the same result.

let listOfKeysToMatch = List<String>()
listOfKeysToMatch.append("302AC133-3980-41F3-95E8-D3E7F639B769")
listOfKeysToMatch.append("54ECC485-4910-44E5-98B9-0712BB99783E")
listOfKeysToMatch.append("71FE403B-30CD-4E6C-B88A-D6FDBB08C509")
let dogResults2 = realm.objects(DogClass.self).filter("dog_id in %@", listOfKeysToMatch)
for dog in dogResults2 {
print(dog.dog_id, dog.dog_name)
}

How can I filter multiple variables and one of them is a Date in Swift?

When using predicates, you shouldn't embed the variable values inside the predicates, since that can often lead to problems, but should use the %@ inside the predicate and write the variable names after the predicate.

However,the issue was with mixing up the comparison operators. I think you misunderstood how variables should be embedded to predicates. Looking at the extract of your Realm model class definition, there's no property named time, only dateFrom. Class properties should either be inside the predicate as normal Strings or referred to using the %K syntax, while the variable names you want to filter for should be referenced to using the %@ syntax.

Below code was tested in a Realm playground and outputs the expected result.

class DeviceDataRealm: Object {
var uuid: String = ""
var resolutionID: Int = 0
var dateFrom: Date = Date()
}

let deviceData = [DeviceDataRealm(value: ["dateFrom":Date.distantPast,"resolutionID":1]),DeviceDataRealm(value: ["dateFrom":Date.distantFuture,"resolutionID":2])]
try! realm.write {
realm.add(deviceData)
}

let searchUuid = "",searchResolutionID = 2, searchDateFrom = Date()
print(realm.objects(DeviceDataRealm.self).filter("uuid = %@ AND resolutionID = %@ AND dateFrom > %@", searchUuid, searchResolutionID, searchDateFrom))

Output:

Results <0x7fcc2c642280> (
[0] DeviceDataRealm {
uuid = ;
resolutionID = 2;
dateFrom = 4001-01-01 00:00:00 +0000;
}
)

realm predicate with an object inside object

You need to use a SUBQUERY to be able to access the properties of the elements of a List in an NSPredicate. The SUBQUERY will evaluate true for every Patient whose list property includes at least 1 RString element whose stringValue matches the provided String.

patients = realm?.objects(Patient.self).filter("name = %@ AND SUBQUERY(list,$element,$element.stringValue == %@).@count>0", "name1", "test")

realm swift - filter objects with a property that starts with a string included in a list

There are a number of ways to do that. One option (which is not really practical in this use case) is to use the Realm Swift Query UI

let results2 = realm.objects(Item.self).where {
$0.name.starts(with: "x0") ||
$0.name.starts(with: "x1") ||
$0.name.starts(with: "x2")
}

As you can see, for a few items it's ok. What if there are dozens? Not very practical. That's where a NSCompoundPredicate really shines. Check this out

var predicateArray = [NSPredicate]()

for name in ['x0', 'x1', 'x2'] {
let predicate = NSPredicate(format: "name BEGINSWITH[cd] %@", name)
predicateArray.append(predicate)
}

let compoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicateArray)

let results = realm.objects(Item.self).filter(compoundPredicate)

Way more practical as the elements in the list can be as many as needed.

There are some other options as well but the NSPredicate route is suggested in this use case.



Related Topics



Leave a reply



Submit