Mongodb $group聚合中的$REDUCT和$regex,以便显示长度

Mongodb $group聚合中的$REDUCT和$regex,以便显示长度,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我想我这里有一个相当复杂的问题——不确定我是否能做到这一点 我有一个有地址和数据字段的数据。数据字段是十六进制值。我想运行一个聚合,按照地址和十六进制数据的长度对数据进行分组。所有数据都将以16个字符的长度输入,但该数据的长度应以字节计算 我想我必须获取数据,去掉尾随的00(使用regex00+$),然后将该数字除以2得到长度。在那之后,我将不得不按地址和最终字节长度分组 一个示例数据集是: {addr:829, data:'4100004822000000'} {addr:829, data:

我想我这里有一个相当复杂的问题——不确定我是否能做到这一点

我有一个有地址和数据字段的数据。数据字段是十六进制值。我想运行一个聚合,按照地址和十六进制数据的长度对数据进行分组。所有数据都将以16个字符的长度输入,但该数据的长度应以字节计算

我想我必须获取数据,去掉尾随的00(使用regex00+$),然后将该数字除以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}
我想要的结果是:

{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
中,我一次通过
数据
两个字符,检查它们是否等于
“00”
。每次它们不存在时,我都会将值更新到序列中的位置。因为它返回最后一个非“00”字符的位置,所以我们向它添加2,以找到结尾的零字符串的起始位置,然后在$group中,我们将其除以2以获得真正的长度

在示例数据上,这将返回:

{ "_id" : { "addr" : 229, "length" : 4 } }
{ "_id" : { "addr" : 506, "length" : 8 } }
{ "_id" : { "addr" : 829, "length" : 5 } }

您可以添加一个
$project
阶段,将字段名称转换为您想要返回的名称。

数据字段实际上是字符串数据类型吗?还是二进制类型?如果是字符串,那绝对有可能。如果是二进制的,那么很可能不是。我认为这很接近,但我相信我需要使用正则表达式来删除尾随的00。如果正在计算的数据字段等于008031000000000,则此例程返回的长度为1.5,而不是预期的3。00是第一个字节,80是第二个字节,31是第三个字节。另外,如果您使用像0000032f00000015这样的数据字符串,我希望它的长度为8,而此方法计算的长度为4。不,它不是。试试看。第一个返回3,第二个返回8。你从哪里得到1.5分和4分的?