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

Sortering efter maksimalt matrixfelt, stigende eller faldende

Det grundlæggende problem med det, du spørger om her, kommer ned til, at de pågældende data er inden for et "array", og derfor er der nogle grundlæggende antagelser fra MongoDB om, hvordan dette bliver håndteret.

Hvis du har anvendt en sortering i "faldende rækkefølge", vil MongoDB gøre præcis, hvad du beder om, og sortere dokumenterne efter den "største" værdi af det angivne felt i arrayet:

.sort({ "revisions.created": -1 ))

Men hvis du i stedet sorterer i "stigende" rækkefølge, er det omvendte selvfølgelig sandt, og den "mindste" værdi tages i betragtning.

.sort({ "revisions.created": 1 })

Så den eneste måde at gøre dette på betyder at finde ud af, hvilken dato der er den maksimale dato fra dataene i arrayet, og derefter sortere på det resultat. Dette betyder grundlæggende at anvende .aggregate() , som for meteor er en operation på serversiden, og er desværre noget som dette:

Collection.aggregate([
    { "$unwind": "$revisions" },
    { "$group": {
        "_id": "$_id",
        "name": { "$first": "$name" },
        "revisions": { "$push": "$revisions" },
        "number": { "$first": "$number" }
        "maxDate": { "$max": "$revisions.created" }
    }},
    { "$sort": { "maxDate": 1 }
])

Eller i bedste fald med MongoDB 3.2, hvor $max kan anvendes direkte på et matrixudtryk:

Collection.aggregate([
    { "$project": {
        "name": 1,
        "revisions": 1,
        "number": 1,
        "maxDate": {
            "$max": {
                "$map": {
                    "input": "$revisions",
                    "as": "el",
                    "in": "$$el.created"
                }
            }
        }
    }},
    { "$sort": { "maxDate": 1 } }
])

Men i virkeligheden er begge ikke så gode, selvom MongoDB 3.2-tilgangen har langt mindre overhead end hvad der er tilgængeligt for tidligere versioner, er den stadig ikke så god, som du kan få med hensyn til ydeevne på grund af behovet for at passere gennem data og arbejde ud af værdien at sortere efter.

det bedste ydeevne, "behold altid" sådanne data, du får brug for "uden for" arrayet. Til dette er der $max "update"-operator, som kun erstatter en værdi i dokumentet "hvis" den angivne værdi er "større end" den eksisterende værdi, der allerede er der. dvs.:

Collection.update(
    { "_id": "qTF8kEphNoB3eTNRA" },
    { 
        "$push": {
            "revisions": { "created": new Date("2016-02-01") }            
        },
        "$max": { "maxDate": new Date("2016-02-01") }
    }
)

Det betyder, at den værdi, du ønsker, "altid" allerede vil være til stede i dokumentet med den forventede værdi, så det er bare nu et simpelt spørgsmål om at sortere på det felt:

.sort({ "maxDate": 1 })

Så for mine penge ville jeg gå gennem de eksisterende data med enten .aggregate() tilgængelige erklæringer, og brug disse resultater til at opdatere hvert dokument til at indeholde et "maxDate"-felt. Skift derefter kodningen af ​​alle tilføjelser og revisioner af matrixdata for at anvende den $max "opdatering" ved hver ændring.

At have et solidt felt frem for en beregning giver altid meget mere mening, hvis du bruger det ofte nok. Og vedligeholdelsen er ret enkel.

Under alle omstændigheder, i betragtning af ovenstående anvendte eksempeldato, som er "mindre end" de andre maksimale datoer, ville vende tilbage for mig i alle former:

{
        "_id" : "5xF9iDTj3reLDKNHh",
        "name" : "Lorem ipsum",
        "revisions" : [
                {
                        "number" : 0,
                        "comment" : "Dolor sit amet",
                        "created" : ISODate("2016-02-11T01:22:45.588Z")
                }
        ],
        "number" : 1,
        "maxDate" : ISODate("2016-02-11T01:22:45.588Z")
}
{
        "_id" : "qTF8kEphNoB3eTNRA",
        "name" : "Consecitur quinam",
        "revisions" : [
                {
                        "comment" : "Hoste ad poderiquem",
                        "number" : 1,
                        "created" : ISODate("2016-02-11T23:25:46.033Z")
                },
                {
                        "number" : 0,
                        "comment" : "Fagor questibilus",
                        "created" : ISODate("2016-02-11T01:22:45.588Z")
                },
                {
                        "created" : ISODate("2016-02-01T00:00:00Z")
                }
        ],
        "number" : 2,
        "maxDate" : ISODate("2016-02-11T23:25:46.033Z")
}

Hvilket korrekt placerer det første dokument øverst i sorteringsrækkefølgen med hensyn til "maxDate".




  1. Hvordan sorterer man i mangust?

  2. E11000 duplikatnøglefejlindeks i mongodb mongoose

  3. Microservices Architecture til meget hyppig dataadgang; i hukommelsesløsninger?

  4. Fuld tekst søgemuligheder for MongoDB opsætning