MongoDB 怎么合并多属性子文档
MongoDB能通过嵌套子文档,可方便灵活记录子文档的多个属性,了解更多的内容细节。如有集合 blog, 其子文档 access 下有 append、edit、manager、read,希望按 NAME 分组,合并其下的 uids,且数据不重复。具体数据如下:
{ |
{ "_id" : ObjectId("99014006e4b0aaac99a104af"), "access" : { "append" : { "uids" :[ ObjectId("94f9bfb0aa6a19084789ca69")], "level" : [4] }, "edit" : {"level" : [5], "uids" : [ ObjectId("94f9bfb0aa6a19084789ca92")]}, "manager" : { "uids" : [ ], "level" : [1] }, "read" : { "uids" : [ ObjectId("94f9bfb0aa6a19084789ca92"), ObjectId("94f9bfb0aa6a19084789ca70")], "level" : [3 ] } }, "name" : "article" } ……. |
用 MongoDB 脚本实现思路,可采用 $addFields 将对象转换为 KV 数组, $unwind 将数组拆解, 按 NAME 分组合并子记录,后面还要再次拆解分组,直到将 uids 合并为止,实现过程比较烦琐。
使用集算器, 可按 name 分组,对本组的 uids 值合并去重,实现比较容易。集算器安装包可去 润乾网站 下载,运行时需要一个授权,免费版本就够用。
我们将上述事例实现步骤:
1. 在集算器中编写脚本 blog.dfx:
A | B | |
1 | =mongo_open("mongodb://localhost:27017/local") | / 连接 MongDB 数据库 |
2 | =mongo_shell(A1,"blog.find(,{_id:0};{name:1})") | / 获取集合 blog 数据 |
3 | =A2.group(name; ~.conj(access.read.uids|access.append.uids| access.edit.uids|access.manager.uids).id(): uids) | / 按 name 分组,合并各子文档下的 uids,并去重 |
4 | >A1.close() | / 关闭连接 |
A3 | name | uids |
article | [94f9bfb0aa6a19084789ca69,94f9bfb0a…] | |
story | [94f9bfb0aa6a19084789ca60,94f9bfb0a…] | |
… |
A3:按 name 分组,合并本组各文档的 uids,并去除重复。
集算器提供了 JDBC 接口,脚本 blog.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://");
// 调用脚本 blog.dfx
st=con.createStatement();
ResultSet rst = st.executeQuery("call blog");
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 脚本》。
英文版