Querying objects

51 views
Skip to first unread message

Vil

unread,
Apr 10, 2014, 12:27:49 PM4/10/14
to cqengine...@googlegroups.com
Hi,

Is it possible to make a query on a field that is located in a child object? 

Example:
class Person{
 string name;
 int age;
 Address address;
}

class Address{
  Long id;
  int num;
  String street;
  String city;
  String postcode;
}

I would like to find the People who have an  Address.num equal to 85?

What is the best approach to do that with CQEngine? 

Thanks
Vincent

Niall Gallagher

unread,
Apr 10, 2014, 3:03:26 PM4/10/14
to cqengine...@googlegroups.com
Hi Vil,

Yes, you can write an attribute which does that.

The attribute will be of type <Person, Integer>. It will be supplied the Person object, and its implementation should return person.address.num.

Basically, think of an attribute as a function. It is supplied a Person object, and its task is to return a value associated with that person (the value of person.address.num in this case).

HTH,
Niall


--
-- You received this message because you are subscribed to the "cqengine-discuss" group.
http://groups.google.com/group/cqengine-discuss
---
You received this message because you are subscribed to the Google Groups "cqengine-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cqengine-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Vil

unread,
Apr 11, 2014, 4:28:08 AM4/11/14
to cqengine...@googlegroups.com
Hi Niall,

Thanks for your answer!
In the case of a 1-1 relationship between objects it's clear!

But what's happens for a relationship 1-*?
In my example could we consider a list of Address instead of an Address for the Person
class Person{
 string name;
 int age;
 List<Address> addresses;
}

class Address{
  Long id;
  int num;
  String street;
  String city;
  String postcode;
}

What is the approach to  find People who have an  Address.num equal to 85?

Regards
Vincent

Niall Gallagher

unread,
Apr 11, 2014, 6:46:46 AM4/11/14
to cqengine...@googlegroups.com
Hi Vincent,

Use a MultiValueAttribute in that case. It will work.

Thanks,
Niall

Vil

unread,
Apr 11, 2014, 7:10:47 AM4/11/14
to cqengine...@googlegroups.com
Hi Niall,

Ok for the MultiValueAttribute. 
But now, how i could use this attribute to retrieve Person with a num address equal to 85?? 

class Person{
 string name;
 int age;
 List<Address> addresses;

 static Attribute<Person, Address> ADDRESS = MultiValueAttribute<Person, Address>(){
       public List<Address> getValues(Person person) {
            return person.addresses;
        }
    };
}

class Address{
  Long id;
  int num;
  static Attribute<Address, Integer> NUM = SimpleValueAttribute<Address, Integer>(){
       public Integer getValues(Address address) {
            return address.num;
        }
    };
}

IndexedCollection persons = CQEngine.newInstance();
persons = fillWithPerson();
persons.retrieve(?????); // get persons with num address equal to 85

Regards
Vincent

Niall Gallagher

unread,
Apr 11, 2014, 7:22:37 AM4/11/14
to cqengine...@googlegroups.com
Hi Vincent,

You don't need an attribute of type <Address, Integer>.

You just need one attribute of type <Person, Integer>:

 static Attribute<Person, Integer> ADDRESS_NUMBER = MultiValueAttribute<Person, Integer>(){
       public List<Integer> getValues(Person person) {
            return <a list of the address numbers for this person>;
        }
    };
}

...
persons.retrieve(equal(Person.ADDRESS_NUMBER, 85)); // get persons with num address equal to 85



--

Vil

unread,
Apr 11, 2014, 8:01:41 AM4/11/14
to cqengine...@googlegroups.com
Ok! Thanks a lot Niall!

Vincent

Vil

unread,
Apr 11, 2014, 10:58:08 AM4/11/14
to cqengine...@googlegroups.com
If now i would like to make a query to retrieve Person who have an Address num equal to 85 in the city "NEW YORK"?
I could use :
persons.retrieve(and(equal(Person.ADDRESS_NUMBER, 85), equal(Person.ADDRESS_CITY, "NEW YORK");

But i think the results will not be the expected result. The query retrieve a list of Person who have a num address equal to 85 and an address in "NEW YORK" (but not necessarily tat num 85!).

Is there an issue?

Regards
Vincent

Le vendredi 11 avril 2014 13:22:37 UTC+2, Niall a écrit :

Niall Gallagher

unread,
Apr 11, 2014, 1:55:29 PM4/11/14
to cqengine...@googlegroups.com
Yes that query is like the following in SQL:

SELECT * FROM Person
WHERE EXISTS SELECT 1 FROM Addresses WHERE Address.personId = Person.personId AND Address.city = 'New York'
AND EXISTS SELECT 1 FROM Addresses WHERE Address.personId = Person.personId AND Address.num = 85;

You need something like:

SELECT * FROM Person
WHERE EXISTS SELECT 1 FROM Addresses WHERE Address.personId = Person.personId AND Address.city = 'New York' AND Address.num = 85;

So you need to create an association in your query. One option is to define an attribute of type <Person, Pair<String, Integer>>, where the pair is String address.city, Integer address.num.
Then you can query the collection by supplying the sought combination of city and num:
persons.retrieve(equal(Person.CITY_NUM, Pair.of("New York", 85));

Another option is to break out addresses into a separate IndexedCollection, and do a JOIN between the collections.

HTH,
Niall


Reply all
Reply to author
Forward
0 new messages