1

I have a following classes:

class Document{
    Map<EnumChannelType, Channel> data;
    //some more fields
}
class Channel{
    String topic;
    //some more fields
}

enum EnumChannelType{
    BASIC_CHANNEL(1), ADVANCED_CHANNEL(2),......;
    int value;
    //constructor and some methods
}

Now I want to query on topic inside Channel. If channelType is known, we can easily query as below:

Query<Document> createQuery(EnumChannelType channelType, String topic){
    Query<Document> query = dao.createQuery().disableValidation();
    query.field("data." + channelType.name() + ".topic").equal(topic);
    return query;
}

But what if I want to get query for given only topic (channelType can be anything)? How can we create query for this?

One option is using or as follows:

Query<Document> createQueryForTopic(String topic) {
    Query<Document> query = dao.createQuery().disableValidation();
    // add all possible Channel Types
    query.or(query.criteria("data." + EnumChannelType.BASIC_CHANNEL.name() + ".topic").equal(topic),
            query.criteria("data." + EnumChannelType.ADVANCED_CHANNEL.name() + ".topic").equal(topic),
            /*...add criteria for all possible channel types*/);
    return query;
}

But this is not feasible if EnumChannelType is changing over time or if EnumChannelType has large number of members (like BASIC_CHANNEL(1), ADVANCED_CHANNEL(2),....).

I'm looking for something like...

Query<Document> createQuery(String topic){
    Query<Document> query = dao.createQuery().disableValidation();
    // use some regex instead of ????
    query.field("data." + ???? + ".topic").equal(topic);
    return query;
}
N D Thokare
  • 1,703
  • 6
  • 35
  • 57
  • I think this might be the same question as http://stackoverflow.com/questions/10901151/mongodb-query-without-field-name. – Trisha Jul 05 '13 at 12:55
  • I'm expecting solution something like explained in [how-to-perform-wildcard-search-in-mongodb-using-java](http://stackoverflow.com/questions/11552976/how-to-perform-wildcard-search-in-mongodb-using-java) . But I'm unable to see how to use it to query on `keys` of `map`.. (look in my example, `EnumChannelType` are used as key in map) – N D Thokare Jul 05 '13 at 13:14
  • My point is that you can do this on Map values, but not on Keys. The link I've posted points out that you can't query key (i.e. field) names in MongoDB. So I don't think you can do this. – Trisha Jul 05 '13 at 13:17
  • ya, that's right. Still thinking if there is another trick to handle this situation. – N D Thokare Jul 05 '13 at 13:20
  • Yes there is, but you'll need to change the structure of your document to use arrays instead, like in the answer to the other question. – Trisha Jul 05 '13 at 13:21

1 Answers1

1

I almost sure that Morphia and MongoDB doesn't support regex on field names. In this case, the best option is use $or operator. You could traverse the whole enum to avoid errors:

List<Criteria> criterias = new ArrayList<Criteria>();
for(EnumChannelType v : EnumChannelType.values()) {
    criterias.add(query.criteria("data." + v.name() + ".topic").equal(topic));
}

query.or(criterias.toArray(new Criteria[criterias.size()]);

Remember that $or operator executes queries in parallel and then merge the results.

Info: http://docs.mongodb.org/manual/reference/operator/or/#op._S_or

N D Thokare
  • 1,703
  • 6
  • 35
  • 57
Miguel Cartagena
  • 2,576
  • 17
  • 20