Search code examples
mongodbpipelinetruncate

MongoDb - Help for pipeline with $trunc


My data :

[
    { total: 7421356 }, 
    { total: 79421356 },
    { total: 105457854 },
    { total: 1054578540 },
    { total: 10545785400 },
]

I would like to have something like :

[
    { val: 7000000, count 1 },
    { val: 70000000, count 1 },
    { val: 100000000, count: 1 },
    { val: 1000000000, count 1 }
]

Actually i use this pipeline :

{
    $addFields: {
        length: {
            $multiply: [
                {
                    $add: [
                        {
                            $strLenCP: {
                                $toString: "$val",
                            }
                        },
                        -1
                    ]
                },
                -1
            ]
        },
    },
},
{
    $project: {
        value: {
            $trunc: ["$val", "$length"],
        },
        _id: 0,
    }
},
{
    $group: {
        _id: "$value",
        count: {
            $sum: 1
        }
    }
}, 
{
    $project: {
        value: "$_id",
        count: 1, 
        _id: 0,
    }
},
{
    $sort: {
        value: 1
    }
}

I have a problem when i have data like "10545785400". It seems his length it too long and for my data "7421356" his result is now "0".

I thought the documents were going through the pipeline individually but it doesn't appear to be. My first data seems to use the length of my last.

I hope someone can help me even if my explanations are not very clear.

EDIT : It seems to be a "type" problem. Data with greater than 1.000.000.000 are double not int32 EDIT 2 : It works with "24760000000" but not with "25661674539". I really don't understand why. They are stored in Double format.


Solution

  • tl;dr


    The doubles are being converted to scientific notation, and that's taking into account to measure the string length, which is 9 in most or all of the fields. As you said the type of those numbers is double.

    See a working example here, converting the string to number before cutting off the data:

    db.collection.aggregate({
      $addFields: {
        length: {
          $multiply: [
            {
              $add: [
                {
                  $strLenCP: {
                    $toString: {
                      $toLong: "$total"
                    },
                    
                  }
                },
                -2
              ]
            },
            -1
          ]
        },
        
      }
    },
    {
      $project: {
        value: {
          $toLong:{
            $trunc: [
            "$total",
            "$length"
          ],
          }
        },
        _id: 0,
        
      }
    })
    

    Detail

    • You can't convert those big numbers to int using $toInt because the numbers are large. Large being larger than 10^10