Reputation: 529
class Dog: Object {
@objc dynamic var name = ""
let owners = List<Owner>()
}
Here, dogs can belong to more than one owner. So, say I have a particular Owner object. How can I set up a query to get all dogs that have that owner in their owners
list?
func allDogsFor(owner: Owner) -> [Dog]? {
let query = realm.objects(Owner.self).filter???
}
Upvotes: 0
Views: 273
Reputation: 35648
This is an answer to your specific question.
Using the same Dog class you have shown in the question, you are asking how to query the Dogs' owners property for a specific owner and you want to return all of the dogs that have that owner.
There are a couple of ways to go about it so here's one way:
Suppose you have an owner with the last_name of Smith - first we want to get that specific owner object and then query all of the Dog Lists for it
let ownerResults = realm.objects(OwnerClass.self).filter("last_name == 'Smith'")
if let smithOwner = ownerResults.first {
let dogResults = realm.objects(DogClass.self).filter("ANY owners == %@", smithOwner)
for dog in dogResults {
print(dog.dog_name)
}
}
And then a second option (as mentioned in another answer) is to use LinkingObjects. Linking objects 'automatically' create a link (inverse relationship) back to another object.
So take a look at these classes
class OwnerClass: Object {
let dogList = List<DogClass>()
}
and
class DogClass: Object {
let owners = LinkingObjects(fromType: OwnerClass.self, property: "dogList")
}
the cool thing here is that when we create a dog class and add it to the owner
let owner = OwnerClass()
owner.dogList.append(aDog)
then write it to realm
let realm = try Realm()
try! realm.write {
realm.add(owner)
}
that dog is also added to realm and the link established.
To revisit the question;
say I have a particular Owner object. How can I set up a query to get all dogs that have that owner in their owners list
To re-state that
I want to know all the dogs that are in a particular owners dogList
In this scenario, you don't need a query. An owner has dogs any dogs added to an owner are part of that owners dogsList
let ownerResults = realm.objects(PersonClass.self).filter("last_name == 'Smith'")
if let smithOwner = ownerResults.first {
let smithsDogs = smithOwner.dogs //no query! this is all
// of the dogs that have smith as an owner
for dog in smithsDogs {
print(dog.dog_name)
}
}
In fact, we don't even need a LinkingObjects property in each dog since if we add those dogs to an owner
owner.dogList.append(objectsIn: [dog0, dog1, dog2])
it's pretty clear there are three dogs in that owners dogList. The LinkingObjects however, will allow us to traverse back to the owner from each dog.
Upvotes: 1
Reputation: 6018
You're looking for inverse relationship. The way it works (from docs):
With linking objects properties, you can obtain all objects that link to a given object from a specific property. A
Dog
object can have a property named owners that contains all of thePerson
objects that have this exactDog
object in their dogs property. Make the owners property of typeLinkingObjects
and then specifying the relationship that it has with thePerson
object.
where Person
it's your Owner
.
I recommend you rewrite little bit your code, because it makes more sense when the owner
has dogs
. Basic example could be:
final class Owner: Object {
let dogs = List<Dog>()
}
final class Dog: Object {
let owners = LinkingObjects(fromType: Owner.self, property: "dogs")
}
let dogsForOwner = owner.dogs
let ownersOfADog = dog.owners
Upvotes: 1