MongoDB程序开发之使用Java驱动
在工作中使用到了MongoDB,平时也看了一些资料,感觉MongoDB官网内develop zone有个不错的manual,很多资料都可以查到,地址如下:http://www.mongodb.org/display/DOCS/Manual
?
另外,本blog主要记录一下使用mongodb java driver来访问数据库的一些总结。
?
?主要是由createMongoInstance()方法完成初始化工作。
protected static final Mongo mongoInstance = createMongoInstance();private static Mongo createMongoInstance() { MongoOptions mo = new MongoOptions(); mo.socketKeepAlive=true; mo.autoConnectRetry = true; mo.maxAutoConnectRetryTime=10; mo.connectionsPerHost = 40; mo.connectTimeout = 20 * 1000; mo.socketTimeout = 60 * 1000; try { if (DatabaseProject.DB_CONFIG.containsKey("mongodb.ips")) { return new Mongo(getServerAddrsFromConf("mongodb"),mo); } return new Mongo(new ServerAddress(DatabaseProject.DB_CONFIG.getString("mongodb.ip"), DatabaseProject.DB_CONFIG.getInt("mongodb.port")),mo); } catch (Throwable e) { DatabaseProject.LOGGER.error("Failed to init mongodb", e); throw new ExceptionInInitializerError(e); } }
? 其中有一些数据库配置直接写在配置文件里了,在MongoJavaDriverDAO中初始化一部分数据:
?
public void insertCollData(){//如果该collection不存在则会自动创建DBCollection parentcoll = getCollection("ParentColl");DBCollection childcoll = getCollection("ChildColl");for(int i=0;i<1000;i++){DBObject document = new BasicDBObject();document.put("intData", 1000+i);document.put("longData", System.currentTimeMillis());document.put("strData", UUID.randomUUID().toString());document.put("doubleData", 1.123+i);document.put("createDate", new Date());document.put("booleanData", true);DBObject innerDoc = new BasicDBObject();innerDoc.put("innertype", "string");innerDoc.put("innerContent", "string"+i);document.put("documentData", innerDoc);parentcoll.insert(document);DBObject childDocument = new BasicDBObject();childDocument.put("parentId", document.get("_id"));childDocument.put("createDate", new Date());List list = new ArrayList();list.add("str" + i%10);list.add("str" + i%20);list.add(new BasicDBObject("arr"+(i%10),(i%10)));list.add(new BasicDBObject("arr"+(i%20),(i%20)));childDocument.put("arrays",list);childcoll.insert(childDocument);}System.out.println("ParentColl Count:"+parentcoll.count());System.out.println("ChildColl Count:"+childcoll.count());}
?其中getCollection方法会获取集合,不存在的话会自动创建一个。getCollection方法如下:
?
public static DBCollection getCollection(String collectionName){return getDB().getCollection(collectionName);}
?现在创建了2个集合ParentColl、ChildColl,并初始化了数据。
查询相关方法:
?
/** * 查询全部数据 */public void findColl(){coll = getCollection("ParentColl");DBCursor cur = coll.find();while(cur.hasNext()){ System.out.println(cur.next()); }System.out.println("Count:"+coll.count());}/** * 根据ObjectId查询 */public void findById(String id){coll = getCollection("ParentColl");DBCursor cur = coll.find(new BasicDBObject("_id", new ObjectId(id)));//直接用string查不出来while(cur.hasNext()){ System.out.println(cur.next()); }}/** * And多条件查询 */public void findByAndQuery(int intData,long longData){coll = getCollection("ParentColl");BasicDBObject query = new BasicDBObject();query.put("intData", intData);query.put("longData", longData);System.out.println(coll.findOne(query));}/** * OR多条件查询 */public void findByORQuery(int lte,int gt,long longData){coll = getCollection("ParentColl");BasicDBObject query=new BasicDBObject();BasicDBObject longdata = new BasicDBObject("longData", longData);BasicDBObject intdata = new BasicDBObject("intData", new BasicDBObject().append("$gt", gt).append("$lte",lte));BasicDBList cond=new BasicDBList();cond.add(longdata);cond.add(intdata);query.put("$or", cond);DBCursor cur = coll.find(query);while(cur.hasNext()){ System.out.println(cur.next()); }}/** * IN查询 */public void findByINQuery(int value1,int value2){coll = getCollection("ParentColl");BasicDBObject query=new BasicDBObject();BasicDBList cond=new BasicDBList();cond.add(value1);cond.add(value2);query.put("intData",new BasicDBObject("$in", cond));DBCursor cur = coll.find(query);while(cur.hasNext()){ System.out.println(cur.next()); }}/** * NOT查询 */public void findByNotQuery(int value1,int value2){coll = getCollection("ParentColl");BasicDBObject query=new BasicDBObject();BasicDBList cond=new BasicDBList();cond.add(value1);cond.add(value2);query.put("intData",new BasicDBObject("$nin", cond));System.out.println("Count:"+coll.find(query).count());}/** * 获取结果集第一条 */public void fetchFirstQuery(int value1,int value2){coll = getCollection("ParentColl");BasicDBList cond = new BasicDBList();cond.add(value1);cond.add(value2);BasicDBObject query = new BasicDBObject().append("intData",new BasicDBObject("$nin",cond));System.out.println(coll.findOne(query));}/** * 查询文档部分列 */public void querySomeKey(){coll = getCollection("ParentColl");DBCursor cur = coll.find(new BasicDBObject(),new BasicDBObject("intData",true));while(cur.hasNext()){ System.out.println(cur.next()); }}/** * 查询内嵌文档 */public void queryInnerDocument(){coll = getCollection("ParentColl");BasicDBObject map = new BasicDBObject();map.put("innertype","string");map.put("innerContent","string0");DBCursor cur = coll.find(new BasicDBObject("documentData",map));while(cur.hasNext()){ System.out.println(cur.next()); }}/** * 查询内嵌部分文档 */public void querySubInnerDocument(){coll = getCollection("ParentColl");DBCursor cur = coll.find(new BasicDBObject("documentData.innerContent","string0"));while(cur.hasNext()){ System.out.println(cur.next()); }}/** * 查询分页文档 */public void queryByPage(int skipNum,int pageNum){coll = getCollection("ParentColl");DBCursor cur = coll.find().skip(skipNum).limit(pageNum);while(cur.hasNext()){ System.out.println(cur.next()); }}/** * 查询文档某列是否存在 */public void queryExists(){coll = getCollection("ParentColl");DBCursor cur = coll.find(new BasicDBObject("longData",new BasicDBObject("$exists",true)));while(cur.hasNext()){System.out.println(cur.next());}}/** * 查询文档排序 */public void sortDocument(){coll = getCollection("ParentColl");DBCursor cur = coll.find().sort(new BasicDBObject("intData",-1));//1:asc / -1:descwhile(cur.hasNext()){System.out.println(cur.next());}}
不难发现主要用到BasicDBObject、BasicDBList、DBCursor这三个类。BasicDBObject好比一个map,好比使用json查询中的{}?。BasicDBList是个list,用于or,nin等条件查询。DBCursor用于遍历结果集。其实只要将对应的json查询使用这3个类转化一下,就能写出对应的java代码了。
?
更新相关:
?
/** * 更新文档1 */public void updateDocument(){DB db = getDB();//由于mongodb中使用连接池的原因,getLastError()需要再次从连接池中获取连接.//保证update操作和getLastError()使用同一个连接.db.requestStart();coll = db.getCollection("ParentColl");WriteResult result = coll.update(new BasicDBObject("intData",1100),new BasicDBObject("$set", new BasicDBObject("booleanData",false)));System.out.println("update count:"+result.getN());if(result.getLastError().ok()){//获取上次操作结果是否有错误.System.out.println("update document success.");}else{System.out.println(result.getLastError().getErrorMessage());}db.requestDone();}/** * 更新文档2 */public void updateMultiDocument(){DB db = getDB();db.requestStart();coll = db.getCollection("ParentColl");//第三个参数:如果没有该文档是否创建,第四个参数:是否更新全部匹配条件的文档.WriteResult result = coll.update(new BasicDBObject("booleanData",false),new BasicDBObject("$set", new BasicDBObject("booleanData",true)),false,true);System.out.println("update count:"+result.getN());if(result.getLastError().ok()){//获取上次操作结果是否有错误.System.out.println("update document success.");}else{System.out.println(result.getLastError().getErrorMessage());}db.requestDone();}
?注意requestStart、requestDone方法保证使用同一个数据库连接。WriteResult记录更新结果。?
?
索引相关:
?
/** * 创建唯一索引 */public void createIndexes(){coll = getCollection("ParentColl");BasicDBObject index = new BasicDBObject();index.put("intData",1);//1:asc / -1:descindex.put("unique",true);//唯一索引coll.createIndex(index);}/** * 查询索引信息 */public void getIndexes(){coll = getCollection("ParentColl");List<DBObject> indexInfo = coll.getIndexInfo();System.out.println(indexInfo);}/** * 删除索引信息 */public void dropIndexes(){coll = getCollection("ParentColl");//删除的索引必须跟创建的索引名称\排序\是否唯一都相同才能删除BasicDBObject index = new BasicDBObject();index.put("intData",1);index.put("unique",true);coll.dropIndex(index);}
?对于文档可能还会对数组操作:
?
/** * 取出文档中的数组 */public void queryArray(){coll = getCollection("ChildColl");DBCursor cur = coll.find(new BasicDBObject(),new BasicDBObject("arrays",1));while(cur.hasNext()){BasicDBObject bo = (BasicDBObject)cur.next();List<BasicDBObject> list = (List<BasicDBObject>)bo.get("arrays");System.out.println(list.toString());}}/** * 查询数组内是否包含某元素 */public void queryElementInArray(){coll = getCollection("ChildColl");BasicDBObject query = new BasicDBObject();BasicDBObject obj = new BasicDBObject();obj.put("arr0",0);query.put("arrays", new BasicDBObject("$elemMatch",obj));DBCursor cur = coll.find(query);while(cur.hasNext()){System.out.println(cur.next());}}/** * 数组内包含元素的值 */public void queryElementArray(){coll = getCollection("ChildColl");BasicDBObject obj = new BasicDBObject();obj.put("arrays", "str0");obj.put("arrays.arr0",0);obj.put("arrays.arr10",10);DBCursor cur = coll.find(obj);while(cur.hasNext()){System.out.println(cur.next());}}/** * push(pushAll) array element */public void pushElementInArray(String _id){DB db = getDB();db.requestStart();coll = getCollection("ChildColl");//WriteResult result = coll.update(new BasicDBObject("_id", new ObjectId(_id)),new BasicDBObject("$push",new BasicDBObject("arrays",new BasicDBObject("arr99","99"))));List<BasicDBObject> list=new ArrayList<BasicDBObject>();list.add(new BasicDBObject("arr99",99));list.add(new BasicDBObject("arr100",100));WriteResult result = coll.update(new BasicDBObject("_id", new ObjectId(_id)),new BasicDBObject("$pushAll",new BasicDBObject("arrays",list)));System.out.println("update count:"+result.getN());if(result.getLastError().ok()){System.out.println("update document success.");}else{System.out.println(result.getLastError().getErrorMessage());}db.requestDone();}/** * pull(pullAll) array element */public void pullElementInArray(String _id){DB db = getDB();db.requestStart();coll = getCollection("ChildColl");List<BasicDBObject> list=new ArrayList<BasicDBObject>();list.add(new BasicDBObject("arr99",99));list.add(new BasicDBObject("arr100",100));//WriteResult result = coll.update(new BasicDBObject("_id", new ObjectId(_id)),new BasicDBObject("$pull",new BasicDBObject("arrays",new BasicDBObject("arr100",100))));WriteResult result = coll.update(new BasicDBObject("_id", new ObjectId(_id)),new BasicDBObject("$pullAll",new BasicDBObject("arrays",list)));System.out.println("update count:"+result.getN());db.requestDone();}/** * pop array element(1,last;-1,first) */public void popElementInArray(String _id){coll = getCollection("ChildColl");WriteResult result = coll.update(new BasicDBObject("_id", new ObjectId(_id)),new BasicDBObject("$pop",new BasicDBObject("arrays",-1)));//1,last;-1,firstSystem.out.println("update count:"+result.getN());}/** * addToSet And Each array element */public void addToSetAndEachElementInArray(String _id){coll = getCollection("ChildColl");List list = new ArrayList();list.add("str0");list.add("str1");list.add(new BasicDBObject("arr99",99));WriteResult result = coll.update(new BasicDBObject("_id", new ObjectId(_id)),new BasicDBObject("$addToSet",new BasicDBObject("arrays",new BasicDBObject("$each",list))));//1,last;-1,firstSystem.out.println("update count:"+result.getN());}/** * 按数组位置更新文档(查询条件需要包含更新内容,$为数组位置占位符,只更新匹配到的第一个文档.) */public void updatePositionInArray(String _id){coll = getCollection("ChildColl");WriteResult result = coll.update(new BasicDBObject("arrays.arr0", 100),new BasicDBObject("$set",new BasicDBObject("arrays.$.arr0",101)));System.out.println("update count:"+result.getN());}
??以上都是一些基本的查询、更新操作,当然还有一些如map reduce和关联查询等复杂的方法,我将另写一篇blog总结一下。
?
参考文献包括:《mongodb权威指南》、《mongodb管理与开发精要》,另外文章开头提到的MongoDB官网内的develop zone也是很不错的资料来源。
?
?