sql >> Databasteknik >  >> NoSQL >> MongoDB

Hur man sorterar dokument baserat på längden på ett Array-fält

Vad du verkar mena här är att du vill "sortera" dina resultat baserat på "längden" på "svars"-matrisen, snarare än en "egenskap" som kallas "längd" som din syntax antyder. För att ta reda på, skulle den syntaxen vara omöjlig här eftersom din modell är "referenserad", vilket innebär att den enda data som finns i arrayfältet i dokumenten i denna samling är ObjectId värden för dessa refererade dokument.

Men du kan göra detta med .aggregate() metoden och $size operatör:

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

En aggregeringspipeline fungerar i etapper. Först finns det ett $projekt för fälten i resultaten, där du använder $size för att returnera längden på den angivna arrayen.

Nu finns det ett fält med "längden", du följer stegen med $sort och $limit som tillämpas som sina egna steg inom en aggregeringspipeline.

Ett bättre tillvägagångssätt skulle vara att alltid behålla egenskapen length för din "svars"-array i dokumentet. Detta gör det enkelt att sortera och fråga på utan andra operationer. Att underhålla detta är enkelt med $inc operatör som du $push eller $pull objekt från arrayen:

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

    }
)

Eller tvärtom när du tar bort:

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

    }
)

Även om du inte använder atomoperatorerna så gäller samma principer där du uppdaterar "längden" allt eftersom. Sedan är det enkelt att fråga med en sortering:

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

});

Eftersom fastigheten redan finns i dokumentet.

Så gör det antingen med .aggregate() utan ändringar av din data, eller ändra din data så att den alltid inkluderar längden som en egenskap och dina frågor kommer att vara mycket snabba.



  1. MongoEngine Document Object som gjorts med from_json sparas inte

  2. MongoDB Chain Replication Basics

  3. Infoga data i MongoDB med PHP

  4. Läs BSON (mongoDB) till POJO med GSON och TypeAdapter