MongoDB 如何通过数组字段进行关联查找
从关联表记录数组中查找符合条件的数据, 用给定的字段组合成新表。
如有两集合 users, workouts,数组字段 users.WorkId 与 workouts._id 有关联。
users | _id | Name | WorkId |
1000 | xxx | [2,4,6] | |
1002 | yyy | [1,3,5] |
workouts | _id | Date | Book |
1 | 1/1/2001 | Othello | |
2 | 2/2/2001 | A Midsummer Night's Dream | |
3 | 3/3/2001 | The Old Man and the Sea | |
4 | 4/4/2001 | GULLIVER'S TRAVELS | |
5 | 5/5/2001 | Pickwick Papers | |
6 | 6/6/2001 | The Red and the Black | |
7 | 7/7/2001 | Running |
Name | _id | Date | Book |
xxx | 2 | 2/2/2001 | A Midsummer Night's Dream |
xxx | 4 | 4/4/2001 | GULLIVER’S TRAVELS |
xxx | 6 | 6/6/2001 | The Red and the Black |
yyy | 1 | 1/1/2001 | Othello |
yyy | 3 | 3/3/2001 | The Old Man and the Sea |
yyy | 5 | 5/5/2001 | Pickwick Papers |
用 MongoDB 脚本实现思路,可用 $lookup 函数将 users,workouts 两个集合关联查询,用 unwind 拆解 users. workouts成记录,并将它们提升到预层 (与 NAME 同层),再显示需要的列,实现过程比较烦琐。
使用集算器, 只要将 workouts._id 存在 users.WorkId 中的记录的 name 追加到 workouts 集合即可,实现比较容易。
集算器安装包可去润乾网站下载,运行时需要一个授权,免费版本就够用。
我们将上述描述事例实现步骤:
1. 在集算器中编写脚本workout.dfx:
A | B | |
1 | =mongo_open("mongodb://127.0.0.1:27017/raqdb") | / 连接 MongDB 数据库 |
2 | =mongo_shell(A1,"users.find()").fetch() | / 获取集合 users 数据 |
3 | =mongo_shell(A1,"workouts.find()").fetch() | / 获取集合 workouts 数据 |
4 | =A2.conj(A3.select(A2.WorkId.pos(_id)).derive(A2.name:Name)) | / 查询序表 A3 的 _id 值存在于序表 A2 中 WorkId 数组的记录, 并追加 name 字段,返回合并的序表。 |
5 | >mongo_close(A1) | / 关闭连接 |
2. 执行脚本返回结果:
_id | Date | Book | Name |
2 | 2/2/2001 | A Midsummer Night's Dream | xxx |
4 | 4/4/2001 | GULLIVER’S TRAVELS | xxx |
6 | 6/6/2001 | The Red and the Black | xxx |
1 | 1/1/2001 | Othello | yyy |
3 | 3/3/2001 | The Old Man and the Sea | yyy |
5 | 5/5/2001 | Pickwick Papers | yyy |
集算器提供了 JDBC 接口,脚本 workout.dfx 很容易集成到 Java 中:
public static void doWorkout() {
Connection con = null;
java.sql.Statement st;
try{
Class.forName("com.esproc.jdbc.InternalDriver");
con = DriverManager.getConnection("jdbc:esproc:local://");
st=con.createStatement();
// 调用脚本 workout.dfx
ResultSet rst = st.executeQuery("call workout");
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 脚本》。
英文版