sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongoose välj subdoc-fält

Så här hanterar MongoDB grundläggande projektion med arrayelement. Medan du kan göra något så här:

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

})

Och det skulle bara returnera "upvotes"-fältet från underdokumenten i kommentarsfältet för alla dokument som matchar villkoret och alla arrayelement, naturligtvis, du kan inte kombinera detta med en vald positionsprojektion med positional $ operatör. Detta härrör i grunden från "teorin" det allmänt du vill faktiskt returnera hela arrayen. Så det är så det alltid har fungerat och kommer sannolikt inte att förändras snart.

För att få det du vill behöver du de utökade funktionerna för dokumentmanipulering som erbjuds av aggregationsramverk . Detta ger dig mer kontroll över hur dokumenten returneras:

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 moderna versioner av MongoDB sedan 2.6 kan du till och med göra detta:

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) {

    }
)

Och som använder $map och $setDifference operatörer att göra en "in-line"-filtrering av arrayinnehållet utan att först bearbeta en $unwind skede.

Så om du vill ha mer kontroll över hur dokumentet returneras, så är aggregeringsramverket sättet att göra det när du arbetar med inbäddade dokument.




  1. Installera MongoDB på CentOS 8

  2. Hur hittar man de närmaste paren (Hamming Distance) av en sträng av binära fack i Ruby utan O^2-problem?

  3. MongoDB-fråga för dokument äldre än 30 sekunder

  4. MongoDb primär replika blir sekundär om sekundär misslyckas