问题
I have some problems while implementing filters in mongodb using morphia POJO mapper.
In my class (for example SampleClass
), when i try to access the fields of an @Entity
class (in our case it's Person
), I find the field access works fine, using dot notation for general fields like int, string, maps or direct embedded objects.
The issue is I could not understand how it works for the case of a "List of Objects" referenced in the Person
class. (Assume here, a person can have many addresses, so this Person
class has a field addresses
which holds a list of Address
objects)
@Entity
Class Person
{
String name;
int age;
String type;
private Map<String, String> personalInfo= new HashMap<String, String>();
@Reference
List<Address> addresses = new ArrayList<Address>;
}
@Entity
Class Address
{
String streetName;
int doorNo;
}
For example, I want to apply a filter on streetName
of the Address
object which is in the addresses
List
public class SampleClass
{
private Datastore ds;
Query<Node> query;
CriteriaContainer container;
// connections params etc....
public List<Person> sampleMethod()
{
query = ds.find( Person.class ).field( "type" ).equal( "GOOD");
container.add( query.criteria( "name" ).containsIgnoreCase("jo" ));
// general String field in the Person Class ---- OKAY, Work's Fine
container.add( query.criteria( "personalInfo.telephone" ).containsIgnoreCase( "458" ) );
// Map field in the Person Class, accessing telephone key value in the map --- OKAY, Work's Fine
container.add( query.criteria( "addresses.streetname").containsIgnoreCase( "mainstreet" ) );
// List of address object in the Person Class, name of the field is 'addresses'
// ----NOT OKAY ????????? -- Here is the problem it returns nothing, even though some value exists
return readTopography( query.asList() );
}
}
Am I doing something wrong while accessing the objects in a list?
回答1:
"addresses" field is a @Reference we cannot use "addresses.name" as a field in a criteria. It should be a criteria where addresses field is in a "List< Key< Address > >" :
Query<Person> personQuery = ds.createQuery(Person.class);
Query<Address> addressQuery = ds.createQuery(Address.class);
addressQuery.criteria("streetName").containsIgnoreCase("mainstreet");
container.add(personQuery.criteria("addresses").in(addressQuery.asKeyList()));
System.out.println(personQuery.asList());
regards, sadish
回答2:
Your query you actually try would query an subdocument addresses
with the field streetname
. So you will only get documents which have addresses as a concrete address not a list of addresses. To match all Persons containing at least one address matching use $elemMatch
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray .
But I'm not sure If Morphia is able to perform such queries, with your schema at all. Keep in mind that your actual Document isn't containing those addresses embedded, instead it contains only dbrefs http://www.mongodb.org/display/DOCS/Database+References . So if morphia isn't smart enough to convert your query it will not succeed, as mongoDB doesn't know DBRefs at all (as this is only some driver convention).
So for the case morphia doesn't offer this functionality you need to query different. At first you need to query your Addresses collection for addresses matching your condition. Collect those ObjectIds and use them with $elemMatch
and $in
in your Person Collection query, to filter out all persons not having such an address, along with your further filter options. You need to keep in mind that you don't have some relational System which does the joining for you.
回答3:
Its looks like tyop for me container.add( query.criteria( "addresses.streetname").containsIgnoreCase( "mainstreet" ) );
.
I think streetname
needs to be changed to streetName
.
I have been using morphia for a year now. AFAIK, container.add( query.criteria( "addresses.streetName").containsIgnoreCase( "mainstreet" ) );
should work fine.
来源:https://stackoverflow.com/questions/10723320/field-access-for-lists-of-objects-in-a-class-via-morphia-in-mongodb