MongoDB 如何合并相同属性的不同字段
MongoDB作为文档型数据库,可方便灵活存储文档,属性相同或相似的数据可采用不同的形式来记录。如有集合 users, 其中用户 July 与 Tom 电话字段记录方式不同,一个多字段形式,一个数组形式,希望按 NAME 分组,合并其下的 TEL。具体数据如下:
…… { "_id" : ObjectId("5fd305b4db8950e48f0cf196"), "username" : "July", "gender" : "F", "age" : 17, "TEL1" : "18811223298", "TEL2" : "18581418158", "TEL3" : "15286856439" } |
{ "_id" : ObjectId("5fd30828db8950e48f0cf197"), "username" : "Tom", "gender" : "M", "age" : 15, "TEL" : [ "13800226298", "18511418100", "13986666413" ] } …… |
用 MongoDB 脚本实现思路,可先获取集合的字段名,再根据字段名匹配获取对应的电话字段,再将电话字段数据合并,使用mapreduce遍历处理,实现过程比较烦琐。
使用集算器, 可先找到 TEL 相关的字段,再将其对应的值合并,实现比较容易。集算器安装包可去 润乾网站 下载,运行时需要一个授权,免费版本就够用。
我们将上述事例实现步骤:
1. 在集算器中编写脚本 tels.dfx:
A | B | |
1 | =mongo_open("mongodb://localhost:27017/local") | / 连接 MongDB 数据库 |
2 | =mongo_shell(A1,"users.find(,{_id:0})") | / 获取集合 users 数据 |
3 | =A2.fname().pselect@a(like(~, "TEL*")) | / 找出以 TEL 开头的字段对应的列号 |
4 | =A2.new(username, gender, age, ( t=~.array(), A3.conj(t(~))\[null] ):tels) | / 将电话号码合并,去掉空值,存入新序表的 TELS 字段 |
5 | >A1.close() | / 关闭连接 |
A3 | Member |
5 | |
6 | |
…… |
A4 | username | gender | age | tels |
July | F | 17 | [18811223298,185814…] | |
Tom | M | 15 | [13800226298,185114…] | |
… |
A4:将记录数据存入变量 t,根据电话所在列的序号获取对应的电话号码,再合并。
集算器提供了 JDBC 接口,脚本 tels.dfx 很容易集成到 Java 中:
public static void doWork() {Connection con = null;
java.sql.Statement st;
try{
Class.forName("com.esproc.jdbc.InternalDriver");
con = DriverManager.getConnection("jdbc:esproc:local://");
// 调用脚本 tels.dfx
st=con.createStatement();
ResultSet rst = st.executeQuery("call tels");
System.out.println(rst);
} catch(Exception e){
System.out.println(e);
} finally{
// 关闭连接
if (con!= null) {
try {
con.close();
} catch(Exception e) {
System.out.println(e);
}
}
}
}
对于同属性的字段,可能有相同的字段或不同的字段来记录,都可以借助集算器来实现。
集算器与 JAVA 集成的进一步信息可参考:《Java 如何调用 SPL 脚本》。
英文版