sql >> Database >  >> NoSQL >> MongoDB

Hoe documenten te sorteren op basis van de lengte van een matrixveld

Wat u hier lijkt te bedoelen, is dat u uw resultaten wilt "sorteren" op basis van de "lengte" van de "antwoorden" -array, in plaats van een "eigenschap" genaamd "lengte", zoals uw syntaxis impliceert. Voor de goede orde, die syntaxis zou hier onmogelijk zijn omdat er naar uw model wordt verwezen, wat betekent dat de enige gegevens die aanwezig zijn in het arrayveld in de documenten van deze verzameling de ObjectId zijn waarden van die documenten waarnaar wordt verwezen.

Maar u kunt dit doen met de .aggregate() methode en de $size operator:

Question.aggregate(
    [
        { "$project": {
            "title": 1,
            "content": 1,
            "created": 1,
            "updated": 1,
            "author": 1,
            "answers": 1,
            "length": { "$size": "$answers" }
        }},
        { "$sort": { "length": -1 } },
        { "$limit": 5 }
    ],
    function(err,results) {
        // results in here
    }
)

Een aggregatiepijplijn werkt in fasen. Ten eerste is er een $project voor de velden in de resultaten, waar u $size . gebruikt om de lengte van de opgegeven array te retourneren.

Nu is er een veld met de "lengte", je volgt de fasen met $sort en $limit die worden toegepast als hun eigen fasen binnen een aggregatiepijplijn.

Een betere benadering zou zijn om altijd de eigenschap length van uw "antwoorden" -array in het document te behouden. Dit maakt het gemakkelijk om te sorteren en op te vragen zonder andere handelingen. Het onderhouden hiervan is eenvoudig met behulp van de $inc operator als jij $push of $pull items uit de array:

Question.findByIdAndUpdate(id,
    {
        "$push": { "answers": answerId },
        "$inc": { "answerLength": 1 } 
    },
    function(err,doc) {

    }
)

Of omgekeerd bij het verwijderen:

Question.findByIdAndUpdate(id,
    {
        "$pull": { "answers": answerId },
        "$inc": { "answerLength": -1 } 
    },
    function(err,doc) {

    }
)

Zelfs als u de atomaire operatoren niet gebruikt, zijn dezelfde principes van toepassing wanneer u de "lengte" bijwerkt terwijl u doorgaat. Dan is opvragen met een sortering eenvoudig:

Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {

});

Omdat de woning al in het document staat.

Dus doe het ofwel met .aggregate() zonder wijzigingen in uw gegevens, of verander uw gegevens om altijd de lengte als eigenschap op te nemen en uw zoekopdrachten zullen zeer snel zijn.



  1. MongoDB InsertBatch JObject - Serialisatiefout

  2. Hoe paginering uitvoeren met bereikquery's in MongoDB?

  3. Opzoeken met array van objecten

  4. Hoe geneste objecten in MongoDB invoegen met Laravel 5?