diff --git a/README.textile b/README.textile index c072b44..d43d53e 100644 --- a/README.textile +++ b/README.textile @@ -30,6 +30,8 @@ public class Car extends MongoModel { public String name; public String colour; public int topSpeed; + public Date firstProductionDate; + public boolean underProduction; } @@ -75,7 +77,14 @@ bc.. List toyotas = Car.find("byName", "Toyota").fetch(); List whiteToyotas = Car.find("byNameAndColour", "Toyota", "white").fetch(); -p. Currently the Mongo module only supports the 'And' query operator. +p. A more complete query engine enable SQL Like query, with support followings operators + +bc.. =, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN, IS NULL, IS NOT NULL, AND, OR + +p. To use Boolean and Date criteria, values must be passed in parameters with JPAStyle numbering syntax (?1, ?2 ...) +p. To use mixed logical expression with both AND and OR operators, brackets must be used to avoid priority management / misunderstanding + +bc.. Car.find("name = 'Toyota' and firstProductionDate > ?1 and (colour in ('red', 'blue', 'green') or colour like '%pink%' or speed > 130) and underProduction = ?2", new Date(56), true) h3. Ordering diff --git a/documentation/manual/home.textile b/documentation/manual/home.textile index dea5324..d43d53e 100644 --- a/documentation/manual/home.textile +++ b/documentation/manual/home.textile @@ -31,7 +31,7 @@ public class Car extends MongoModel { public String colour; public int topSpeed; public Date firstProductionDate; - public boolean underProduction; + public boolean underProduction; } diff --git a/lib/play-mongo.jar b/lib/play-mongo.jar index e90a2b1..80c1beb 100644 Binary files a/lib/play-mongo.jar and b/lib/play-mongo.jar differ diff --git a/src/play/modules/mongo/MongoCursor.java b/src/play/modules/mongo/MongoCursor.java index 1f699d5..c29595b 100644 --- a/src/play/modules/mongo/MongoCursor.java +++ b/src/play/modules/mongo/MongoCursor.java @@ -104,7 +104,11 @@ public List fetch(){ */ @SuppressWarnings("unchecked") public T first(){ - return (T)fetch(1,1).get(0); + List limitedList = fetch(1,1); + if (!limitedList.isEmpty()) { + return limitedList.get(0); + } + return null; } /** @@ -117,7 +121,18 @@ public MongoCursor from(int from){ cursor.skip(from); return this; } - + + /** + * Limit the given the number of records. + * + * @param limit - the maximum number of records + * @return - the cursor + */ + public MongoCursor limit(int limit){ + cursor.limit(limit); + return this; + } + /** * Orders the objects pointed to by the cursor, using the * orderBy string. diff --git a/src/play/modules/mongo/MongoDB.java b/src/play/modules/mongo/MongoDB.java index 3dac184..f9d59b8 100644 --- a/src/play/modules/mongo/MongoDB.java +++ b/src/play/modules/mongo/MongoDB.java @@ -21,7 +21,9 @@ import com.mongodb.DBObject; import com.mongodb.Mongo; import com.mongodb.MongoClient; +import com.mongodb.MongoCredential; import com.mongodb.MongoException; +import com.mongodb.ServerAddress; public class MongoDB { @@ -32,6 +34,8 @@ public class MongoDB { private static String host; private static Integer port; private static String dbname; + private static String username; + private static String password; /** * Obtain a reference to the mongo database. @@ -40,13 +44,7 @@ public class MongoDB { */ public static DB db() { if (db == null) { - if (Play.configuration.containsKey("mongo.username") && Play.configuration.containsKey("mongo.password")) { - String username = Play.configuration.getProperty("mongo.username"); - String passwd = Play.configuration.getProperty("mongo.password"); - init(username, passwd); - } else { - init(); - } + init(); } return db; @@ -60,6 +58,8 @@ public static void reset() { host = null; port = null; dbname = null; + username = null; + password = null; init(); } @@ -75,11 +75,20 @@ public static void init() { port = Integer.parseInt(Play.configuration.getProperty("mongo.port", "27017")); dbname = Play.configuration.getProperty("mongo.database", "play." + Play.configuration.getProperty("application.name")); } + if (username == null || password == null) { + username = Play.configuration.getProperty("mongo.username"); + password = Play.configuration.getProperty("mongo.password"); + } Logger.info("initializing DB ["+host+"]["+port+"]["+dbname+"]"); try { - mongo = new MongoClient(host, port); + ServerAddress lSA = new ServerAddress(host, port); + List lCred = new ArrayList(); + if (username != null && password != null) { + lCred.add(MongoCredential.createCredential(username, dbname, password.toCharArray())); + } + mongo = new MongoClient(lSA, lCred); db = mongo.getDB(dbname); } catch (UnknownHostException e) { e.printStackTrace(); @@ -88,11 +97,6 @@ public static void init() { } } - public static void init(String username, String password){ - init(); - db.authenticate(username, password.toCharArray()); - } - /** * Creates an index. * @@ -144,51 +148,6 @@ public static String[] getIndexes(String collectionName) { return indexNames.toArray(new String[indexNames.size()]); } - /** - * Adds a user to the database. We must manually set the readOnly parameter - * because the java mongo API does not yet support it. It will only work - * with database versions > 1.3. - * - * @param username - * @param passwd - * @param readOnly - */ - public static void addUser(String username, String passwd, boolean readOnly) { - db().addUser(username, passwd.toCharArray()); - DBCollection c = db().getCollection("system.users"); - - DBObject userObj = c.findOne(new BasicDBObject("user", username)); - if (userObj != null) { - userObj.put("readOnly", readOnly); - c.save(userObj); - } - } - - /** - * Removes a user from the database. - * - * @param username - */ - public static void removeUser(String username) { - DBCollection c = db().getCollection("system.users"); - - DBObject userObj = c.findOne(new BasicDBObject("user", username)); - if (userObj != null) { - c.remove(userObj); - } - } - - /** - * Authenticates a user against a database. - * - * @param username - * @param password - */ - public static boolean authenticate(String username, String password) { - return db().authenticate(username, password.toCharArray()); - } - - /** * Counts the records in the collection. * @@ -210,7 +169,18 @@ public static long count(String collectionName) { public static long count(String collectionName, String query, Object[] params) { return db().getCollection(collectionName).getCount(createQueryDbObject(query, params)); } - + + /** + * Counts the records in the collection matching the query object + * + * @param collectionName - the queried collection + * @param queryObject - the query object + * @return + */ + public static long count(String collectionName, DBObject queryObject) { + return db().getCollection(collectionName).getCount(queryObject); + } + /** * Provides a cursor to the objects in a collection, matching the query string. * @@ -237,6 +207,18 @@ public static MongoCursor find(String collectionName, Class clazz) { return new MongoCursor(db().getCollection(collectionName).find(), clazz); } + /** + * Provides a cursor to the objects in a collection, matching the query object + * + * @param collectionName - the target collection + * @param queryObject - the query object + * @param clazz - the type of MongoModel + * @return - a mongo cursor + */ + public static MongoCursor find(String collectionName, DBObject queryObject, Class clazz) { + return new MongoCursor(db().getCollection(collectionName).find(queryObject), clazz); + } + public static T findById(String collectionName, Class clazz, ObjectId id) { DBObject query = new BasicDBObject("_id", id); DBObject dbObject = db().getCollection(collectionName).findOne(query); @@ -302,7 +284,20 @@ public static long delete(String collectionName, String query, Object[] params) return deleteCount; } - + + /** + * Deletes models from a collection that match a specific query object + * + * @param collectionName - the collection + * @param queryObject - the query object + * @return - the number of models deleted + */ + public static long delete(String collectionName, DBObject queryObject) { + long deleteCount = db().getCollection(collectionName).getCount(queryObject); + db().getCollection(collectionName).remove(queryObject); + return deleteCount; + } + /** * Deletes all models from the collection. * diff --git a/src/play/modules/mongo/MongoEnhancer.java b/src/play/modules/mongo/MongoEnhancer.java index 50d684e..541d7a6 100644 --- a/src/play/modules/mongo/MongoEnhancer.java +++ b/src/play/modules/mongo/MongoEnhancer.java @@ -89,6 +89,10 @@ private void enhanceMongoEntity(CtClass ctClass, ApplicationClass applicationCla CtMethod count2 = CtMethod.make("public static long count(java.lang.String query, java.lang.Object[] params) { return MongoDB.count(getCollectionName(), query, params); }", ctClass); ctClass.addMethod(count2); + // count3 + CtMethod count3 = CtMethod.make("public static long count(com.mongodb.DBObject queryObject) { return MongoDB.count(getCollectionName(), queryObject); }", ctClass); + ctClass.addMethod(count3); + // find CtMethod find = CtMethod.make("public static MongoCursor find(String query, Object[] params){ return MongoDB.find(getCollectionName(),query,params,"+entityName+".class); }", ctClass); ctClass.addMethod(find); @@ -97,14 +101,22 @@ private void enhanceMongoEntity(CtClass ctClass, ApplicationClass applicationCla CtMethod find2 = CtMethod.make("public static MongoCursor find(){ return MongoDB.find(getCollectionName(),"+entityName+".class); }", ctClass); ctClass.addMethod(find2); + // find3 + CtMethod find3 = CtMethod.make("public static MongoCursor find(com.mongodb.DBObject queryObject){ return MongoDB.find(getCollectionName(),queryObject,"+entityName+".class); }", ctClass); + ctClass.addMethod(find3); + // delete CtMethod delete = CtMethod.make("public void delete() { MongoDB.delete(getCollectionName(), this); }", ctClass); ctClass.addMethod(delete); - // delete + // delete2 CtMethod delete2 = CtMethod.make("public static long delete(String query, Object[] params) { return MongoDB.delete(getCollectionName(), query, params); }", ctClass); ctClass.addMethod(delete2); - + + // delete3 + CtMethod delete3 = CtMethod.make("public static long delete(com.mongodb.DBObject queryObject) { return MongoDB.delete(getCollectionName(), queryObject); }", ctClass); + ctClass.addMethod(delete3); + // deleteAll CtMethod deleteAll = CtMethod.make("public static long deleteAll() { return MongoDB.deleteAll(getCollectionName()); }", ctClass); ctClass.addMethod(deleteAll); diff --git a/src/play/modules/mongo/MongoModel.java b/src/play/modules/mongo/MongoModel.java index b519c7f..d22ab41 100644 --- a/src/play/modules/mongo/MongoModel.java +++ b/src/play/modules/mongo/MongoModel.java @@ -1,6 +1,9 @@ package play.modules.mongo; import org.bson.types.ObjectId; + +import com.mongodb.DBObject; + import play.db.Model; import java.io.Serializable; @@ -33,10 +36,18 @@ public static long count(String query, Object... params) { throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); } - public static MongoCursor find(String query, Object... params) { + public static long count(DBObject queryObject) { throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); } + public static MongoCursor find(String query, Object... params) { + throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); + } + + public static MongoCursor find(DBObject queryObject) { + throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); + } + public static MongoCursor find() { throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); } @@ -53,6 +64,10 @@ public static long delete(String query, Object... params) { throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); } + public static long delete(DBObject queryObject) { + throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); + } + public static long deleteAll(){ throw new UnsupportedOperationException("Please annotate your model with @MongoEntity annotation."); }