sql >> Database teknologi >  >> NoSQL >> MongoDB

Mongoose vælg subdoc-felter

Sådan håndterer MongoDB grundlæggende projektion med array-elementer. Mens du kan gøre noget som dette:

Model.findOne({}, { "comments.upvotes": 1 },function(err,doc) {

})

Og det ville bare returnere "upvotes"-feltet fra underdokumenterne i kommentararrayet for alle dokumenter, der matcher betingelsen og alle array-elementer, selvfølgelig, du kan ikke kombinere dette med en valgt positionel projektion ved hjælp af positional $ operatør. Dette stammer grundlæggende fra "teorien" det generelt du faktisk ønsker at returnere hele arrayet. Så det er sådan, det altid har fungeret og vil sandsynligvis ikke ændre sig snart.

For at få det, du ønsker, har du brug for de udvidede muligheder for dokumentmanipulation, der tilbydes af aggregeringsramme . Dette giver dig mere kontrol over, hvordan dokumenterne returneres:

Model.aggregate(
    [
        // Match the document containing the array element
        { "$match": { "comments._id" : oid } },

        // Unwind to "de-normalize" the array content
        { "$unwind": "$comments" },

        // Match the specific array element
        { "$match": { "comments._id" : oid } },

        // Group back and just return the "upvotes" field
        { "$group": {
            "_id": "$_id",
            "comments": { "$push": { "upvotes": "$comments.upvotes" } }
        }}
    ],
    function(err,docs) {


    }
);

Eller i moderne versioner af MongoDB siden 2.6 kan du endda gøre dette:

Model.aggregate(
    [
        { "$match": { "comments._id" : oid } },
        { "$project": {
            "comments": {
                "$setDifference": [
                    { "$map": {
                        "input": "$comments",
                        "as": "el",
                        "in": {
                            "$cond": [
                                { "$eq": [ "$$el._id", oid ] },
                                { "upvotes": "$$el.upvotes" },
                                false
                            ]
                        }
                    }},
                    [false]
                ]
            }}
        }}
    ],
    function(err,docs) {

    }
)

Og det bruger $map og $setDifference operatører til at foretage en "in-line" filtrering af matrixindholdet uden først at behandle en $unwind scene.

Så hvis du vil have mere kontrol over, hvordan dokumentet returneres, så er aggregeringsrammen måden at gøre det på, når du arbejder med indlejrede dokumenter.




  1. Nodejs + mongodb :Hvordan forespørges $ref felter?

  2. Når du fjerner dokumentet fra en begrænset samling i mongoDB, sker det gennem en fejl?

  3. RedisTemplate udløber virker ikke

  4. forskel mellem aggregat ($match) og find, i MongoDB?