java mongo 去重_MongoDB 如何对嵌套子文档分组去重计算

MongoDB的数据存储使用嵌套结构非常普遍,它通过嵌套子文档,实现一对多的关联关系。但嵌套结构分组进行子文档去重数据计算时,常需要将嵌套结构提升为扁平结构,再通过 $group 聚集运算来实现。

下面以集合 fund 为例说明,按 id 分组获取 shares、trade 子文档下的不重复 fundcode 数量。具体数据如下:

{

"id" : 1,

"shares" : [

{

"fundcode" :   "000001",

"lastshares" : 1230.2,

"agencyno" :   "260",

"netno" : "260"

},

{

"fundcode" :   "000002",

"lastshares" : 213124,

"agencyno" :   "469",

"netno" :   "001"

},

{

"fundcode" :   "000001",

"lastshares" : 10000.8,

"agencyno" : "469",

"netno" :   "002"

}

],

"trade" : [

{

"fundcode" :   "000001",

"c_date" : "20180412",

"agencyno" :   "260",

"netno" :   "260",

"bk_tradetype" : "122",

"confirmbalance" :   1230.2,

},

{

"fundcode" :   "000002",

"c_date" : "20180506",

"agencyno" :   "469",

"netno" :   "001",

"bk_tradetype" :   "122",

"confirmbalance" :   213124,

},

{

"fundcode" :   "000003",

"c_date" : "20190502",

"agencyno" :   "469",

"netno" :   "002",

"bk_tradetype" :   "122",

"confirmbalance" :   10000.8,

"netvalue" : 1,

}

]

}

…….

用 MongoDB 脚本实现思路,用 $group 按 id 分组,提取文档下的 fundcode,再用 $unwind 分别按 shares、trade 拆解成对象,将数据扁平化,再分组时用 $addToSet 去重处理,然后对 shares、trade 下的 fundcode 计数,实现过程比较麻烦。

使用集算器, 可将 trade 子文档整理成序表后,再分组去重计数,实现比较容易。

集算器安装包可去

润乾网站

下载,运行时需要一个授权,免费版本就够用。

我们将上述事例实现步骤:

1.在集算器中编写脚本 fund.dfx:

A

B

1

=mongo_open("mongodb://localhost:27017/local")

/ 连接 MongDB 数据库

2

=mongo_shell(A1,"fund.find(,   {_id: 0})").fetch()

/ 条件过滤集合 fund 数据

3

=A2.trade.conj(if (#==1, t=~.fname(), t=t^~.fname())).id()

/ 取 trade 子文档下的字段交集

4

=A2.run(  trade=trade.new( ${A3.(A3(#)).concat@c()}))

/ 将共有字段数据转换成序表

5

=A2.group(id;   ~.conj(shares.(fundcode)).id().count(): shares,~.conj(trade.(fundcode)).id().count():trade)

/ 按 id 分组,对 shares, trade 下的 fundcode 去重计数

6

>A1.close()

/ 关闭连接

2.      调试执行一下:可看到 A3 格值为:

A3

Member

agencyno

bk_tradetype

……

3.      执行脚本返回结果:

A5

id

shares

trade

1.0

4

6

2.0

3

3

由于子文档 trade 下面的字段结构不一致,需要转换成结构化的序表结构,有利于后面的数据处理。

集算器提供了 JDBC 接口,脚本 fund.dfx 很容易集成到 Java 中:

public static voiddoWork() {

Connection con = null;

java.sql.Statement st;

try{

Class.forName("com.esproc.jdbc.InternalDriver");

con = DriverManager.getConnection("jdbc:esproc:local://");

// 调用脚本 fund.dfx

st=con.createStatement();

ResultSet rst = st.executeQuery("call fund");

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 脚本》。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值