2015-11-24 5 views
10

Sto provando a proiettare FileName e FileSize per tutti i miei file nella mia raccolta con una dimensione di 50 mb o superiore, ma non riesco a concatenare il tipo FileSize poiché ha un tipo di IntMongodb concat int e stringa

voglio la proiezione di essere

{ 
"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" 
    } 
} 

Ma finora posso tornare solo il seguente

{ 
"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 
    } 
} 

la mia domanda:

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"]} 
     } 
    } 

Come concatenare il campo FileSize e "MB"?

risposta

8

Il trucco è quello di utilizzare $substr per eseguire la conversione in una stringa, e un paio di piccoli extra per gestire il punto di precisione decimale:

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

O meglio ancora, si combinano in un unico $project, sia con l'aiuto di $let in versioni successive a MongoDB 2.6, sia in versione long in caso di necessità. Una fase singola pipeline è più efficiente di due:

{ "$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", 
        ] 
       } 
      } 
     } 
    }} 

Quindi, fintanto che si rompe il numero in corrispondenza del punto decimale (via $mod) si può buttare un argomento "lunghezza" al resto della stringa da affrontare con numeri di lunghezza arbitraria. Con il "resto" separato dall'uso di $mod, la lunghezza della stringa con due cifre decimali è sempre "tre", partendo ovviamente dalla seconda posizione per saltare il numero iniziale 0.

ritorni esattamente quello che hai chiesto:

{ 
     "_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" 
} 
14

Aggiungi Fase 2.5: P

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

FileSize è un intero e non v'è alcuna operazione per convertirlo in stringa. Quindi puoi usare hack e usare substr per convertirlo in stringa, 0 per iniziare e -1 resto della stringa.