web-dev-qa-db-fra.com

Mongodb concat int et string

J'essaie de projeter FileName et FileSize pour tous mes fichiers de ma collection avec une taille de 50 Mo ou plus, mais je ne peux pas concaténer le type FileSize car il a le type Int.

Je veux que la projection soit

{
"result" : [ 
    {
        "_id" : ObjectId("5652c399a21dad0bb01b6308"),
        "FileName" : "1234567890.xml",
        "FileSize" : "11.06 MB"
    }, 
    {
        "_id" : ObjectId("5652c399a21dad0bb01b630f"),
        "FileName" : "2468101214.xml",
        "FileSize" : "320.48 MB"
    }, 
    {
        "_id" : ObjectId("5652c399a21dad0bb01b631f"),
        "FileName" : "3691215180.xml",
        "FileSize" : "12.95 MB"
    }
}

Mais jusqu'à présent, je ne peux que retourner ce qui suit

{
"result" : [ 
    {
        "_id" : ObjectId("5652c399a21dad0bb01b6308"),
        "FileName" : "1234567890.xml",
        "FileSize" : 11.0610504150390630
    }, 
    {
        "_id" : ObjectId("5652c399a21dad0bb01b630f"),
        "FileName" : "2468101214.xml",
        "FileSize" : 320.4827098846435500
    }, 
    {
        "_id" : ObjectId("5652c399a21dad0bb01b631f"),
        "FileName" : "3691215180.xml",
        "FileSize" : 12.9519605636596680
    }
}

Ma requête:

    db.MyCollection.aggregate(

  // Pipeline
  [
    // Stage 1
    {
      $match: {
      FileSize: {$gte: 5000000}
      }
    },
    // Stage 2
    {
      $project: {
        FileName: 1,
        FileSize: {$divide: ["$FileSize", 1048576]}
      }
    },
    // Stage 3
    {
        $project:{
            FileName:1,
            FileSize:{$concat:["$FileSize", "MB"]}
        }
     }

Comment concaténer les champs FileSize et "MB"?

14
Jaun Lloyd

Le truc ici consiste à utiliser $substr pour convertir les chaînes en chaîne, et quelques extras pour gérer la précision du point décimal:

    { "$project": {
        "FileName": 1,
        "FileSize": {
            "$concat": [
                { "$substr": [
                    { "$subtract": [ "$FileSize", { "$mod": [ "$FileSize", 1 ] }]},
                    0,
                    -1
                ]},
                { "$substr": [ { "$mod": [ "$FileSize", 1 ] }, 1, 3] },
                " MB",
            ]
        }
    }}

Ou mieux encore, combinez-le en un seul $project, soit à l’aide de $let dans les versions ultérieures à MongoDB 2.6, ou longtemps si nécessaire. Une seule étape de pipeline est plus efficace que deux:

    { "$project": {
        "FileName": 1,
        "FileSize": {
            "$let": {
                "vars": {
                    "FileSize": { "$divide": [ "$FileSize", 1048576 ] }
                },
                "in":{
                    "$concat": [
                        { "$substr": [
                            { "$subtract": [ "$$FileSize", { "$mod": [ "$$FileSize", 1 ] }]},
                            0,
                            -1
                        ]},
                        { "$substr": [ { "$mod": [ "$$FileSize", 1 ] }, 1, 3] },
                        " MB",
                    ]
                }
            }
        }
    }}

Donc, tant que vous séparez le nombre au point décimal (via $mod ), vous pouvez ajouter un argument "length" au reste de la chaîne pour traiter des nombres de longueur arbitraire. Avec le "reste" séparé de l'utilisation de $mod, la longueur de la chaîne à deux décimales est toujours "trois", en commençant bien sûr à partir de la deuxième position afin de sauter le 0 qui précède.

Retourne exactement ce que vous avez demandé:

{
        "_id" : ObjectId("5652c399a21dad0bb01b6308"),
        "FileName" : "1234567890.xml",
        "FileSize" : "11.06 MB"
}
{
        "_id" : ObjectId("5652c399a21dad0bb01b630f"),
        "FileName" : "2468101214.xml",
        "FileSize" : "320.48 MB"
}
{
        "_id" : ObjectId("5652c399a21dad0bb01b631f"),
        "FileName" : "3691215180.xml",
        "FileSize" : "12.95 MB"
}
16
Blakes Seven

Ajouter l'étape 2.5: P

{
    $project:{
        FileName:1,
            FileSize:{$substr:["$FileSize", 0, -1 ]}
    }
}

FileSize est un entier et il n'y a pas d'opération pour le convertir en String. Vous pouvez donc utiliser hack, et utiliser substr pour le convertir en chaîne, 0 pour le début et -1 reste de la chaîne.

23
Hiren S.

C'est maintenant possible dans MongoDB v4.0 en utilisant $ toString operator qui convertit une valeur en chaîne:

db.col.aggregate([
    {
        $project: {
            FileSize: { $concat: [ { $toString: "$FileSize" }, " MB" ] }
        }
    }
])
1
mickl