在管理支撑能力平台项目中,流程审批单数据实施方案采用MongoDB存储管理技术。此技术比传统关系型数据的设计、开发简单了很多。
但是查询开发方面,需要自行编码来解决,比较麻烦,因此想到做几个查询服务,来提高需求响应效率。
查询服务设计目标:
使用MongoDB Client Shell和函数,就像SQL语句中DML一样,快速实施查询,尽量少写后端代码,以类似配置方式来提供查询服务。
SQL | MongoDB | 说明 |
select * from user where age<40 order by c | db.user.find({“age”:{$lt:40}}).sort({c:1}) | 查询 |
select count(*) from user where age<40 | db.user.find({“age”:{$lt:40}}).count() | 查询、汇总 |
select a,b from user where age>8 | db.user.find({“age”:{$gt:8},{a:1,b:1}}) | 查询制定列 |
通过上述对比,可以通过分段输入查询命令,简化Java编程开发,例如本文所设计的输入参数有:查询条件、查询指定列、排序、分页。
/**
* 按简易MongoDB命令行方式查询数据,操作符去掉"$"符号
* @param jsonStr, MongoDB Client查询shell命令字符串
* @param jsonKey, 返回规定数据列(字段)
* @param collection, 查询集合
* @param page, 页码
* @param pageSize, 每页行数,如果pageSize=0,则是不分页
* @param sortKey, 排序shell命令字符串,默认按_id排序
* @return 返回JSON字符串; collCount, 返回查询结果集记录数;data, 返回多行查询结果
*/
public static String findMongoSimplePage(String jsonStr,String jsonKey, String collection,int page,int pageSize,String sortKey){
String docStr = null;
//查询条件
BasicDBObject queryObject = new BasicDBObject();
//查询返回指定字段
BasicDBObject queryKey = new BasicDBObject();
//查询排序字段
BasicDBObject querySortKey = new BasicDBObject();
// 获取指定的collection
DBCollection coll = MongoDBUtil.getCollection(collection);
JSONObject jsonObject = JSONObject.fromObject(jsonStr);
Iterator<String> tmp = jsonObject.keys();
while (tmp.hasNext()){
String keyStr = tmp.next();
try{
JSONObject relationObject = jsonObject.getJSONObject(keyStr);
Iterator<String> tmpRelation = relationObject.keys();
if (tmpRelation.hasNext()){
String relationKey = tmpRelation.next();
String relationStr = relationObject.getString(relationKey);
queryObject.append(keyStr, new BasicDBObject("$" + relationKey,relationStr));
}else{
}
}catch(Exception e){
//e.printStackTrace();
String val = jsonObject.getString(keyStr);
//按MongoDB默认关键字查询,需要特殊处理解析
if (keyStr.equals("_id")){
queryObject.append(keyStr,new ObjectId(val) );
}else{
queryObject.append(keyStr, val);
}
}
}
String key[] = jsonKey.split(",");
for (int i=0;i<key.length;i++){
queryKey.append(key[i], 1);
}
JSONObject sortObject = JSONObject.fromObject(sortKey);
Iterator<String> tmpSort = sortObject.keys();
while (tmpSort.hasNext()){
String keyStr = tmpSort.next();
int val = sortObject.getInt(keyStr);
querySortKey.append(keyStr, val);
}
DBCursor cursor = null;
long collCount = coll.find(queryObject,queryKey).count();
//查询结果排序处理
if (querySortKey.size()>0 && pageSize >0){
cursor = coll.find(queryObject,queryKey).sort(querySortKey).skip((page-1)*pageSize).limit(pageSize);
}else if (querySortKey.size()>0 && pageSize == 0){
//排序,不分页
cursor = coll.find(queryObject,queryKey).sort(querySortKey);
}else if (querySortKey.size()==0 && pageSize >0){
//不排序,分页
cursor = coll.find(queryObject,queryKey).skip((page-1)*pageSize).limit(pageSize);
}else{
cursor = coll.find(queryObject,queryKey);
}
List<DBObject> list = new ArrayList<DBObject>();
while (cursor.hasNext()){
DBObject dboject = cursor.next();
System.out.println(dboject.toString());
list.add(dboject);
}
//构造返回JSON字符串
docStr = "{collCount:" + collCount + ",";
docStr = docStr + "queryStr:" + queryObject.toString() + ",";
docStr = docStr + "queryKey:" + queryKey.toString() + ",";
docStr = docStr + "data:" + list.toString() + "}";
return docStr;
}
调用服务例一,参考SQL语句为select sdept,schemeName,beginTime,overTime from ZFSP order by beginTime。
其中,输入查询条件为空,表示方式为“{}”。
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<FindMongoSimplePage xmlns="http://unicom.com/common/attachment" preserveSpace="no" qAccess="0" qValues="">
<jsonStr>{}</jsonStr>
<jsonKey>sdept,schemeName,beginTime,overTime</jsonKey>
<collection>ZFSP</collection>
<page>1</page>
<pageSize>10</pageSize>
<sortKey>{beginTime:1}</sortKey>
</FindMongoSimplePage>
</SOAP:Body>
</SOAP:Envelope>
带查询条件的({beginTime:{gt:2016-03-01}}),调用查询服务。
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<FindMongoSimplePage xmlns="http://unicom.com/common/attachment" preserveSpace="no" qAccess="0" qValues="">
<jsonStr>{beginTime:{gt:2016-03-01}}</jsonStr>
<jsonKey>schemeName,beginTime</jsonKey>
<collection>ZFSP</collection>
<page>1</page>
<pageSize>5</pageSize>
<sortKey>{beginTime:1}</sortKey>
</FindMongoSimplePage>
</SOAP:Body>
</SOAP:Envelope>
返回结果为JSON格式的字符串,内容中标识出查询结果集总数(collCount:82)、查询条件(queryStr:{ “beginTime” : { “$gt” : “2016-03-01”}})、查询指定列(queryKey:{ “schemeName” : 1 , “beginTime” : 1},),以及核心多行数据(data)。
反回结果如下:
<data>
<FindMongoSimplePageResponse xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://unicom.com/common/attachment" preserveSpace="no" qAccess="0" qValues="">
<tuple>
<old>
<findMongoSimplePage>
<findMongoSimplePage>{collCount:82,queryStr:{ "beginTime" : { "$gt" : "2016-03-01"}},queryKey:{ "schemeName" : 1 , "beginTime" : 1},data:[{ "_id" : { "$oid" : "56d7969084ae9c1c2c4c47d8"} , "schemeName" : "折扣" , "beginTime" : "2016-03-03"}, { "_id" : { "$oid" : "56dcd58284ae9c1c2c4c47e4"} , "schemeName" : "114747" , "beginTime" : "2016-03-07"}, { "_id" : { "$oid" : "56dcf31884ae9c1c2c4c47ea"} , "schemeName" : "888" , "beginTime" : "2016-03-07"}, { "_id" : { "$oid" : "56dcdc2484ae9c1c2c4c47e8"} , "schemeName" : "2344" , "beginTime" : "2016-03-07"}, { "_id" : { "$oid" : "56dcf62084ae9c1c2c4c47ec"} , "schemeName" : "11111" , "beginTime" : "2016-03-07"}]}</findMongoSimplePage>
</findMongoSimplePage>
</old>
</tuple>
</FindMongoSimplePageResponse>
</data>
注意事项:
- MongoDB查询操作符有“$”,与JQuery有冲突;
- MongoDB默认id为“_id”,非字母开头的关键字,与JSON解析有冲突;
- 其他逻辑操作符,例如“$or”等,将在后续实际应用中,逐渐丰富查询服务;
- 前端解析反馈回来分页显示的多行数据,也需要封装成易用的函数,例如:与关系型数据库交互获取数据等,后续补充;
- 本文查询分页使用skip函数,网友分享建议尽量少用,后续再优化。
参考:
《(转)Mongodb 与sql 语句对照》 2011.11
《java操作mongodb(分页)》 2014.12 褚金辉
《初学MongoDB实践笔记——安装、创建数据库、保存及查询数据 》 2015.01 肖永威