Alexander Khitev
Alexander Khitev

Reputation: 6851

How to filter Realm objects by list

I have a DeviceContactModel and a DeviceContactPhoneModel that inherit from Object (Realm). The DeviceContactModel has a List <DeviceContactPhoneModel>. I want to filter the DeviceContactModel by one of the DeviceContactPhoneModel property. I made the test code, but it calls the app crash. Please tell me how it can be implemented? Thanks.

    class DeviceContactModel: Object, Mappable {

        @objc dynamic var id = ""
        @objc dynamic var givenName = ""
        @objc dynamic var familyName = ""
        @objc dynamic var updateTimestamp = 0.0

        var isNew = false

        let phones = List<DeviceContactPhoneModel>()

    }

final class DeviceContactPhoneModel: Object, Mappable {

    @objc dynamic var id = ""
    @objc dynamic var contactID = ""
    @objc dynamic var updateTimestamp = 0.0
    @objc dynamic var countryCode: Int64 = 0
    @objc dynamic var nationalNumber: Int64 = 0
    @objc dynamic var fullNumber: Int64 = 0

}

Test function

private func getDeviceContacts(_ phoneNumbers: [Int64]) -> [DeviceContactModel] {
        do {
            let realm = try Realm()
            let deviceContacts = Array(realm.objects(DeviceContactModel.self).filter("phones.fullNumber IN %@", phoneNumbers))
            return deviceContacts
        } catch {
            debugPrint(error.localizedDescription)
            return []
        }
    }

Crash log Invalid predicate', reason: 'Key paths that include an array property must use aggregate operations

Upvotes: 1

Views: 3377

Answers (2)

a.masri
a.masri

Reputation: 2469

try this solution

If you use a to-many relationship, You use an ANY operator

Please read this well so you understand what to use because there is another operator ex ALL,ANY,NONE Predicate Programming Guide

 private func getDeviceContacts(_ phoneNumbers: [Int64]) -> [DeviceContactModel] {
            do {
                let realm = try Realm()
                let deviceContacts = Array(realm.objects(DeviceContactModel.self).filter("ANY phones.fullNumber IN %@", phoneNumbers))
                return deviceContacts
            } catch {
                debugPrint(error.localizedDescription)
                return []
            }
        }

Upvotes: 3

Alfredo Luco G
Alfredo Luco G

Reputation: 974

May you can use:

var numbers: [[DeviceContactModel]] = [[]]
for number in phoneNumbers{
   let deviceContacts = Array(realm.objects(DeviceContactModel.self))
   let deviceWithNumber = deviceContacts.filter({ $0.fullNumber == number })
   numbers.append(deviceWithNumber)
}
return numbers.flatMap({ $0 })

Upvotes: 0

Related Questions