Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm Swift - Find by IDs

Tags:

swift

realm

I need to query Realm objects using a list of ids, id being the object's primary key. I have tried the following:

// Query a list of Dogs by their _ids
let doggoIds = ["1", "2", "3", "1", "2"]
realm.objects(Dog.self).filter("_id IN %@", doggoIds)
// Result: [Dog1, Dog2, Dog3]

The list of ids contains duplicates, but as you can see the result is a list of unique Dog objects.

I'm wondering if anyone can think of a different way to write this query so that we get a nice Results<Dog> collection from that list of ids that includes duplicates. Thanks!

like image 750
EmilienHuet Avatar asked Oct 23 '25 02:10

EmilienHuet


2 Answers

Realm results contain unique objects so the easiest solution is to query for each dog and add the result to an array. CompactMap does this well as it filters out nil.

let listOfDogsToFind = ["Fido", "Dino", "Sport", "Fido", "Cupid"]

let dogArray = listOfDogsToFind.compactMap { dogName -> DogClass? in
    if let result = realm.objects(DogClass.self).filter("dog_name == %@", dogName).first {
        return result
    }
    return nil
}

for dog in dogArray {
    print("dog name: \(dog.dog_name)")
}

assume Cupid doesn't exist, here's the output

dog name: Fido
dog name: Dino
dog name: Sport
dog name: Fido

Edit:

For clarity, once an object is read into Results, reading it again within the same query will not create a duplicate. e.g. Reading object with ID: 1 and then within the same query, reading that object again, only one instance of the object will be in results. So if (per a comment) objects with ID's of [1, 2, 3, 1, 2, 3] were read in a single query, the end Result object will only have a single instance of objects 1, 2 and 3. However, since we are reading one at a time and adding to an array, duplicates will exist in the array.

like image 107
Jay Avatar answered Oct 24 '25 16:10

Jay


Realm.objects().filter returns a list of "live", managed objects. It will not return duplicates because there is only one object matching the primary key. In order to accomplish what you want, you'll need to create an 'unmanaged' duplicate of each object and make your own array of those unmanaged objects map each returned instance into your own array.

A la:

let doggoIds = [1, 2, 3, 1, 2]
    for managedMuttId in doggoIds {
        if let managedMutt = realm.object(ofType: Dog.self, forPrimaryKey: managedMuttId) {
            // unmanaged.append(Dog(value: managedMutt))
            duplicateList.append(managedMutt)
        }
    }
like image 27
elight Avatar answered Oct 24 '25 17:10

elight