Issue 225 in morphia: AND queries does not allow several filters on the same criteria

26 views
Skip to first unread message

mor...@googlecode.com

unread,
Feb 9, 2011, 8:33:22 AM2/9/11
to morphia...@googlegroups.com
Status: New
Owner: ----
Labels: Type-Defect Priority-Low

New issue 225 by johan.se...@gmail.com: AND queries does not allow several
filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

For instance,

query.and(
query.criteria("name").contains("Jack"),
query.criteria("name").startsWithIgnoreCase("Hip")
);

One would expect that the query would match names that start with Hip and
also contains Jack.
The produced query however looks as follows:

{ "name" : { "$regex" : "^Hip" , "$options" : "i"}}

I.e. the first criteria is missing.

What version are you using? (Morphia/Driver/MongoDB)
morphia 1.0 snapshot / mongodb 1.6.5 / driver 2.4


mor...@googlecode.com

unread,
Feb 9, 2011, 9:51:30 AM2/9/11
to morphia...@googlegroups.com

Comment #1 on issue 225 by scotthernandez: AND queries does not allow
several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

This is a server limitation. http://jira.mongodb.org/browse/SERVER-1089

mor...@googlecode.com

unread,
Feb 11, 2011, 6:18:06 AM2/11/11
to morphia...@googlegroups.com

Comment #2 on issue 225 by johan.se...@gmail.com: AND queries does not
allow several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

Okey thanks, did not know that. How would I work around this when creating
multiple filters for the same field?

mor...@googlecode.com

unread,
Feb 11, 2011, 10:50:57 AM2/11/11
to morphia...@googlegroups.com

Comment #3 on issue 225 by scotthernandez: AND queries does not allow
several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

In this specific case you can work arround it by using hasAnyOf ($in) and
specifying the values in a List.

http://code.google.com/p/morphia/wiki/Query#Methods
http://code.google.com/p/morphia/source/browse/trunk/morphia/src/main/java/com/google/code/morphia/query/FieldEndImpl.java?r=1650#71

In general there aren't always ways to use $in/nin/all to work around this
limitation.

mor...@googlecode.com

unread,
Feb 11, 2011, 10:54:59 AM2/11/11
to morphia...@googlegroups.com

Comment #4 on issue 225 by scotthernandez: AND queries does not allow
several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

Sorry that should be hasAllOf ($all) since you want and behavior.

mor...@googlecode.com

unread,
Feb 15, 2011, 4:02:39 AM2/15/11
to morphia...@googlegroups.com

Comment #5 on issue 225 by johan.se...@gmail.com: AND queries does not
allow several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

Again thanks for your answer. I was hoping to be able to use multiple
filters with startsWith, ignorecase etc.. so the hasAllOf doesn't really
suffice.

mor...@googlecode.com

unread,
Dec 30, 2011, 10:50:36 AM12/30/11
to morphia...@googlegroups.com

Comment #6 on issue 225 by sdeit...@gmail.com: AND queries does not allow
several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

Since 2.0, there is an $and operator, so it would be great if this would be
supported in Morphia.

Complete test case (tested with Morphia 1.00-SNAPSHOT, Java driver 2.7.2,
MongoDB 2.0.1):


public class TestCase
{
@Entity( "documents" )
private static class Document
{
@Id
public ObjectId id;

public List< String > keywords = new ArrayList< String >();
}

public static void main( String[] args ) throws UnknownHostException,
MongoException
{
Morphia morphia = new Morphia();
morphia.mapPackageFromClass( Document.class );

Mongo mongo = new Mongo();
Datastore ds = morphia.createDatastore( mongo, "test" );

ds.delete( ds.find( Document.class ) );

Document doc1 = new Document();
doc1.keywords.add( "foobar" );
doc1.keywords.add( "operator-test" );
ds.save( doc1 );

Document doc2 = new Document();
doc2.keywords.add( "something" );
doc2.keywords.add( "tested" );
ds.save( doc2 );

Query< Document > query = ds.find( Document.class );
query.and( query.criteria( "keywords" ).contains( "foo" ),
query.criteria( "keywords" ).contains( "test" ) );

// should print 1, but prints 2
System.out.println( query.countAll() );

DBCollection documents = mongo.getDB( "test"
).getCollection( "documents" );
BasicDBList criteria = new BasicDBList();
criteria.add( new BasicDBObject( "keywords", new
BasicDBObject( "$regex", "foo" ) ) );
criteria.add( new BasicDBObject( "keywords", new
BasicDBObject( "$regex", "test" ) ) );

// this prints 1 as expected
System.out.println( documents.find( new BasicDBObject( "$and",
criteria ) ).count() );
}
}

mor...@googlecode.com

unread,
Dec 13, 2012, 3:45:34 PM12/13/12
to morphia...@googlegroups.com

Comment #7 on issue 225 by tim.muri...@gmail.com: AND queries does not
allow several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

Any updates on this issue?

mor...@googlecode.com

unread,
May 28, 2013, 3:41:29 PM5/28/13
to morphia...@googlegroups.com

Comment #8 on issue 225 by be.kl...@gmail.com: AND queries does not allow
several filters on the same criteria
http://code.google.com/p/morphia/issues/detail?id=225

Hi,

don't know if this issue is still of interest - but I faced the same
problem when querying for the same field containing different strings in
a "like"-manner with complete wildcard (i.e. field LIKE '%xyz%' and field
like '%abc%' in SQL).
I finally solved it by making use of morphia's pattern-abillity for queries.
Actually the interesting part of code looks like this (sorry, some German
variable names... ;):

Map<String, List> queries = new HashMap<>();
for (Kriterium sb : kriterien) {
if (sb.suchobjekt != null) {
if (!queries.containsKey(sb.feld)) {
queries.put(sb.feld, new ArrayList());
}
if (sb instanceof KriteriumWildcard && ((String)
sb.suchobjekt).trim().length() > 0) {
queries.get(sb.feld).add(Pattern.compile((String)
sb.suchobjekt, Pattern.CASE_INSENSITIVE));
} else {
queries.get(sb.feld).add(sb.suchobjekt);
}
}
}
Query<EDIFACTNachrichtendatei> q =
ds.createQuery(EDIFACTNachrichtendatei.class);
for (Entry<String, List> entry : queries.entrySet()) {
if (entry.getValue().size() > 0) {
q.field(entry.getKey()).hasAllOf(entry.getValue());
}
}

As you can see, the most important trick is to combine the
hasAllOf()-method with morphia's ability to understand regular expressions
as values for this method's parameter objects. I don't know if this is
really good practice but it works pretty well for me. I haven't tried so
far to combine it with several other, different criteria (e.g. not being a
like-pattern but a fixed object), so maybe there'll remain some drawbacks
to still work around when using this strategy.

Ben

--
You received this message because this project is configured to send all
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings
Reply all
Reply to author
Forward
0 new messages