MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Est-il possible d'utiliser la projection de requête sur la même collection qui a une projection $elemMatch ?

Oui, il y a deux façons de procéder. Vous pouvez donc soit utiliser le $elemMatch côté projection comme vous l'avez déjà fait, avec de légères modifications :

Model.findById(id,
   { "comments": { "$elemMatch": {"created.by": "Jane" } } },
   function(err,doc) {

Ou ajoutez simplement à la partie requête et utilisez le $ positionnel opérateur :

Model.findOne(
    { "_id": id, "comments.created.by": "Jane" },
    { "comments.$": 1 },
    function(err,doc) {

L'une ou l'autre manière est parfaitement valable.

Si vous vouliez quelque chose d'un peu plus compliqué que cela, vous pouvez utiliser le .aggregate() méthode et c'est $project opérateur à la place :

Model.aggregate([
    // Still match the document
    { "$match": "_id": id, "comments.created.by": "Jane" },

    // Unwind the array
    { "$unwind": "$comments" },

    // Only match elements, there can be more than 1
    { "$match": "_id": id, "comments.created.by": "Jane" },

    // Project only what you want
    { "$project": {
        "comments": {
            "body": "$comments.body",
            "by": "$comments.created.by"
        }
    }},

    // Group back each document with the array if you want to
    { "$group": {
        "_id": "$_id",
        "comments": { "$push": "$comments" }
    }}
],
function(err,result) {

Ainsi, le cadre d'agrégation peut être utilisé pour bien plus que simplement agréger des résultats. C'est $project l'opérateur vous donne plus de flexibilité que ce qui est disponible pour la projection en utilisant .find() . Il vous permet également de filtrer et de renvoyer plusieurs résultats de tableau, ce qui est également quelque chose qui ne peut pas être fait avec la projection dans .find() .