在$ group聚合中使用$ regex $ reduce,以便显示长度
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在$ group聚合中使用$ regex $ reduce,以便显示长度相关的知识,希望对你有一定的参考价值。
我想我在这里有一个非常复杂的 - 不知道我能不能做到这一点。
我有包含地址和数据字段的数据。数据字段是十六进制值。我想运行一个聚合,按地址分组数据,然后是十六进制数据的长度。所有数据都将以16个字符长的形式出现,但该数据的长度应以字节为单位计算。
我想我必须取数据,去掉尾随的00(使用正则表达式00 + $),并将该数字除以2得到长度。之后,我将不得不按地址和最终字节长度进行分组。
示例数据集将是:
{addr:829, data:'4100004822000000'}
{addr:829, data:'4100004813000000'}
{addr:829, data:'4100004804000000'}
{addr:506, data:'0000108000000005'}
{addr:506, data:'0000108000000032'}
{addr:229, data:'0065005500000000'}
我想要的输出是:
{addr:829, length:5}
{addr:506, length:8}
{addr:229, length:4}
这甚至可以在聚合查询中使用,而不必使用外部代码吗?
答案
如果你的“数据”实际上是你在样本数据中显示的字符串,那么这并不复杂。假设数据存在并设置为某些内容(您可以根据需要添加错误检查),您可以获得所需的结果:
db.coll.aggregate([
{$addFields:{lastNonZero:{$add:[2,{$reduce:{
initialValue:-2,
input:{$range:[0,{$strLenCP:"$data"},2]},
in:{$cond:{
if: {$eq:["00",{$substr:["$data","$$this",2]}]},
then: "$$value",
else: "$$this"
}}
}}]}}},
{$group:{_id:{
addr:"$addr",
length:{$divide:["$lastNonZero",2]}
}}}
])
我使用了两个阶段,但当然如果你愿意,它们可以组合成一个$group
。在$reduce
,我一次通过data
2个字符,检查它们是否等于"00"
。每次他们不是我更新值到我在序列中的位置。因为它返回最后一个非“00”字符的位置,所以我们向它添加2以查找到达结尾的零字符串开始的位置,然后在$ group中我们将其除以2以获得真实长度。
在您的示例数据上,返回:
{ "_id" : { "addr" : 229, "length" : 4 } }
{ "_id" : { "addr" : 506, "length" : 8 } }
{ "_id" : { "addr" : 829, "length" : 5 } }
您可以添加一个$project
阶段,将字段名称转换为您想要返回的字段名称。
以上是关于在$ group聚合中使用$ regex $ reduce,以便显示长度的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Java 中获取 Group.Captures(来自 C# 中的 RegEx)的行为?