web-dev-qa-db-fra.com

Y at-il autre chose si quelque chose dans MongoDB à venir tout en agrégeant

J'ai donc besoin d'un champ personnalisé calculé dans MongoDB comme suit

if( field1 =="A")  ->customfield=10
else if(field1 =="B"  )->customfield=20
else (field1 =="C" ) ->customfield=15

J'utilise l'agrégation avec l'instruction $ project. Mais l'opérateur $ cond n'autorise pas elseif (sous-ramifier le else) et autorise simplement deux branches statiques if et else. Utilisation d'un autre cause imbriquée 

"exception: field inclusion is not allowed inside of $expressions"

Heres ma requête (qui me donne l'erreur)

db.items.aggregate([ { $project :
{
     name: 1,
     customfield:
     {
         $cond: { if: { $eq: [ "$field1", "4" ] }, then: 30,
                else: {
                    if: 
                    { $eq: ["$field1","8"]}, 
                    then: 25, else: 10}}
               }
           }},{ $sort: { customfield: 1 }},{$limit:12}]);

Y at-il une méthode ou une solution de contournement à cela. Je m'excuse s'il s'agit d'une question répétée, mais je n'ai pas réussi à en trouver une similaire.

14
humblerookie

Les mots-clés if..then..else de l'opérateur $cond ne constituent qu'un ajout récent aux versions les plus récentes de MongoDB au moment de la rédaction. L'intention était de la clarté, mais dans ce cas, il semble avoir créé une certaine confusion.

En tant qu'opérateur if..then.else, $cond est en fait un opérateur ternary , comme il serait implémenté dans de nombreux langages de programmation. Cela signifie qu’en tant que condition "en ligne", plutôt que de créer des "blocs" de logique aux conditions, tout ce qui ne remplit pas la première condition appartient à else.

Par conséquent, vous "imbriquez" les instructions plutôt que de suivre les blocs:

db.items.aggregate([
    { "$project": {
        "name": 1,
        "customfield": {
            "$cond": { 
                "if": { "$eq": [ "$field1", "4" ] }, 
                "then": 30,
                "else": {
                    "$cond": {
                        "if": { "$eq": ["$field1","8"]}, 
                        "then": 25, 
                        "else": 10
                    }
                }
            }
        }
    }},
   { "$sort": { customfield: 1 }},
   { "$limit":12 }
]);

Ternaire signifie trois conditions, ni plus ni moins. Donc, toute la logique if..then..else doit être imbriquée.

27
Neil Lunn

MongoDB 3.4 a une nouvelle chose appelée $switch pour cette chose exacte!

$switch: {
   branches: [
      { case: <expression>, then: <expression> },
      { case: <expression>, then: <expression> },
      ...
   ],
   default: <expression>
}

https://docs.mongodb.com/manual/reference/operator/aggregation/switch/

8
nort

si vous utilisez uniquement objet alors

{
    $cond: {
        $and: [
            { if: { $eq: ["$$field1", 'A'] }, then: '10', else: 15 },
            { if: { $eq: ["$$field1", 'B'] }, then: '20', else: 15 },
            { if: { $eq: ["$$field1", 'C'] }, then: '10', else: 15 },
        ]
    }
}

Et si vous utilisez Array find Data 

{
    $map: {
        input: "$fields", as: "field1", in: {
            $cond: {
                $and: [
                    { if: { $eq: ["$$field1", 'A'] }, then: '10', else: 15 },
                    { if: { $eq: ["$$field1", 'B'] }, then: '20', else: 15 },
                    { if: { $eq: ["$$field1", 'C'] }, then: '10', else: 15 },
                ]
            }
        }
    }
}
0
KARNAV PARGI