2017-10-12 5 views
1

J'ai une collection avec des documents comme celui-ci:Obtenir des valeurs distinctes de tableau en fonction des conditions dans le tableau

{ 
"_id" : ObjectId("59df91dae4b03289d79efb4e"), 
    "name" : "TEST", 
    "payload" : [ 
    { 
     "_id" : "ABC", 
     "status": "FALSE" 
    }, 
    { 
     "_id":"DEF", 
    "status": "TRUE" 
    }, 
    { 
     "_id" : "XYZ", 
    "status": "NULL" 
    } 
    ] 
} 

Je suis en train de trouver toutes les payload._id qui ont le statut de VRAI/FAUX. résultat attendu est

["ABC","DEF"] 

Jusqu'à présent, j'ai quelque chose comme ça.

db.collection.distinct('payload._id',{"_id" : "TEST"}) 

Vous ne savez pas comment ajouter des conditions pour les éléments dans le tableau.

Répondre

0

Les conditions d'interrogation avec .distinct() s'appliquent à "docume nt selection "et non les entrées de tableau contenues" dans "le document. Si vous avez besoin de "filtrer" le contenu du tableau, vous appliquez plutôt .aggregate(), ainsi qu'un petit post-traitement pour obtenir uniquement les "valeurs" dans la réponse du tableau.

db.collection.aggregate([ 
    { "$match": { "_id": "TEST" } }, 
    { "$unwind": "$payload" }, 
    { "$match": { "payload.status": { "$in": ["TRUE","FALSE"] } } }, 
    { "$group": { "_id": "$payload._id" } }, 
]).map(d => d._id); 

Les pièces principales sont là la scène du pipeline $unwind que vous faites principalement parce que vous voulez que les valeurs de l'intérieur du tableau à utiliser plus tard comme la clé de $group sur. Cela produit essentiellement un nouveau document pour chaque membre de groupe, mais chaque document contient uniquement ce membre de groupe. C'est "dénormaliser" pour les structures MongoDB qui contiennent des tableaux.

Ensuite, le pipeline $match suivant, fonctionne comme n'importe quelle requête et ne sélectionne que les documents correspondant aux conditions. Puisque tous les membres du tableau sont maintenant des «documents», les entrées non correspondantes (comme les documents) sont exclues. Vous pouvez alternativement utiliser $filter pour extraire tout en restant un tableau, mais puisque nous avons besoin de $unwind pour la prochaine étape, nous pouvons aussi simplement $match.

À ce stade, vous ne disposez plus que des entrées de tableau correspondant aux conditions. Le $group consiste à obtenir des valeurs "distinctes", donc typiquement vous le feriez sur une sélection plus large qu'un simple document ou n'importe quoi où les valeurs ici ne sont pas déjà distinctes. Donc, c'est vraiment garder tout le même comportement de .distinct() intact.

Enfin, depuis la sortie de .aggregate() diffère de la conception de .distinct() en ce qu'elle retourne « documents » dans les résultats, nous utilisons simplement la méthode .map() pour traiter les résultats du curseur et retourner uniquement les « valeurs » de la propriété de document spécifique en tant que "tableau".

+0

Cela a fonctionné. Merci pour l'explication. Modifié la méthode map() comme suit pour l'exécuter sur la carte RoboMongo (function (u) {return u._id; }) –

+0

@AtulPrasad Vous avez probablement une ancienne version de RoboMongo si elle ne comprend pas la syntaxe ES6 d'une flèche '=>'. Je vous suggère de mettre à jour cela car il y a aussi d'autres changements liés à la compatibilité avec les versions modernes de MongoDB. Aussi bienvenue à Stack Overflow. Lorsque vous recevez une réponse appropriée à votre question, vous la marquez comme acceptée (https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) pour indiquer la bonne réponse. –

1

Je suis en train de trouver toutes les payload._id qui ont le statut de VRAI/FAUX

La requête que vous souhaitez exécuter est:

db.collection.distinct('payload._id', { 
    'payload.status': { $in: ["TRUE", "FALSE"] } 
}) 

Une façon plus prolixe le faire serait:

db.collection.distinct('payload._id', { 
    $or: [ 
    {'payload.status': "TRUE" }, 
    {'payload.status': "FALSE" } 
    ] 
}) 
+0

Les conditions de requête dans '.distinct()' ne filtrent pas le contenu du tableau. [Voir la réponse.] (Https://stackoverflow.com/a/46718902/2313887). –

+0

Ne fonctionne pas. Merci! –