How to query property inside nested object (d.Owner.CountryCode == "UK")?


#1

I would like to have something like that:

public class Person : RealmObject
{
 public string CountryCode {get; set; }
}

public class Dog : RealmObject
{
 public Person Owner {get; set; }
}

...

var dogsFromUK = realm.All<Dog>.Where( d => d.Owner.CountryCode == "UK");

This kind of query works fine in Realm Studio, but in code it throws exception:

The left-hand side of the Equal operator must be a direct access to a persisted property in Realm.
Unable to process ‘d.Owner.CountryCode’

How to create this kind of query?


#2

In this case, I would make an inverse relationship to the person model, and query that objects.
You can find more info about it here: inverse relationship


#3

You can’t do that with LINQ, but you can use the string-based query syntax that Realm .NET supports.

You’ll end up with something like: realm.All<Dog>().Filter("Owner.CountryCode == 'UK'").


#4

Actually in real life use case (dogs and owners is just an example) it has inverse relationship.

public class Person : RealmObject
{
 public string CountryCode {get; set; }

 [Backlink(name(Dog.Owner))]
 IQueryable<Dog> Dogs{ get; }
}

public class Dog : RealmObject
{
 public Breed Breed {get; set; }
 public Person Owner {get; set; }
}

But querying persons do not solve the problem. I want dogsFromUK to be ItemsSource for ListView and there are other filter possibilities, lets image someone want bassetsFromUK :slight_smile:

I’m experimenting with wrapping IRealmCollection in FilteredCollection following advises from https://forums.realm.io/t/querying-for-nested-attributes/411/5 thread with some small fix:

private T[] _internal = Enumerable.Empty<T>().ToArray();

to avoid null exception (GetEnumerator is called from InitializeComponent faster than RaiseChanged).

But it seems to not solve the problem. @nirinchev, could you help?

var results = _dogsSubscription.Results;
filteredResults = new FilteredCollection<Dog>(results.AsRealmCollection(), d => d.Owner.CountryCode="UK");

throw exception. Inside, the problem is with RiaseChanged, Where(_filter) part, when I check result, I can see that IEnumerator throw “System.NullReferenceException: Object reference not set to an instance of an object”.

_internal = collection.AsEnumerable().Where(_filter).ToArray();

It happened when there is nested property in _filter. In the other case, for example

filteredResults = new FilteredCollection<Dog>(results.AsRealmCollection(), d => d.Breed==Breed.Basset);

it works fine.

That thread was over one year old, so I have a hope that in current Realm version something new was implemented, especially that as I mentioned before, querying dog.Owner.CountryCode works very nice in RealmStudio.

I will appreciate any suggestion.


#5

As I mentioned, you can’t do that with LINQ. You need to use the string-based filtering.


#6

Thank you for this advice, I will check just now. Previous post I wrote before I read you advice.

And just to confirm after test, problem solved, thank you!


#7

What if the nested attribute is a back pointer to another parent RealmObject? Let’s City has Person(s). And Person has a to-one reference to its parent City.

Can you do realm.All().Filter( "Owner.City.Name == “New York” ) to find all dogs whose owner is in New York?

We have a deeply nested object tree that we do data mining type queries on. Imagine a nested path like A.B.C.D. We need to be able to get “all Ds in a specific A”. Is that possible in Realm?


#8

I’m on my phone and can validate it right now, but I can see no reason why realm.All<D>().Filter("Parent_C.Parnet_B.Parent_A.Id == 123") should not work, where Parent_XXX are properties pointing from the child object to the parent:

public class A : RealmObject
{
    public B B { get; set; }

    // Other properties
}

public class B : RealmObject
{
    [Backlink(nameof(A.B))]
    public IQueryable<A> Parent_A { get; }
}