sql >> Database >  >> NoSQL >> MongoDB

Sorteren op maximaal matrixveld, oplopend of aflopend

Het fundamentele probleem met wat u hier vraagt, komt neer op het feit dat de gegevens in kwestie zich in een "array" bevinden, en daarom zijn er enkele basisaannames gemaakt door MongoDB over hoe dit wordt afgehandeld.

Als u een sortering in "aflopende volgorde" heeft toegepast, zal MongoDB precies doen wat u vraagt ​​en de documenten sorteren op de "grootste" waarde van het opgegeven veld in de array:

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

Maar als u in plaats daarvan in "oplopende" volgorde sorteert, is natuurlijk het omgekeerde waar en wordt de "kleinste" waarde in overweging genomen.

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

Dus de enige manier om dit te doen, is uitzoeken wat de maximale datum is van de gegevens in de array, en dan sorteren op dat resultaat. Dit betekent in feite het toepassen van .aggregate() , wat voor meteor een operatie aan de serverzijde is, helaas zoiets als dit:

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

Of op zijn best met MongoDB 3.2, waar $max kan direct worden toegepast op een array-uitdrukking:

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

Maar eigenlijk zijn beide niet zo geweldig, zelfs als de MongoDB 3.2-aanpak veel minder overhead heeft dan wat beschikbaar is voor eerdere versies, is het nog steeds niet zo goed als je kunt krijgen in termen van prestaties vanwege de noodzaak om de gegevens en werk door te geven de waarde uit waarop moet worden gesorteerd.

Dus voor beste performance, bewaart u "altijd" de gegevens die u nodig heeft "buiten" de array. Hiervoor is er de $max "update"-operator, die alleen een waarde in het document vervangt "als" de opgegeven waarde "groter is dan" de bestaande waarde die er al is. dat wil zeggen:

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

Dit betekent dat de gewenste waarde "altijd" al aanwezig zal zijn in het document met de verwachte waarde, dus het is nu een kwestie van sorteren op dat veld:

.sort({ "maxDate": 1 })

Dus voor mijn geld zou ik door de bestaande gegevens gaan met een van de .aggregate() beschikbare verklaringen, en gebruik die resultaten om elk document bij te werken zodat het een "maxDate"-veld bevat. Wijzig vervolgens de codering van alle toevoegingen en revisies van arraygegevens om dat toe te passen $max "update" bij elke wijziging.

Het hebben van een vast veld in plaats van een berekening is altijd veel logischer als u het vaak genoeg gebruikt. En het onderhoud is vrij eenvoudig.

In ieder geval, gezien de hierboven toegepaste voorbeelddatum, die "minder is dan" de andere maximale datums die aanwezig zijn, zou ik in alle vormen terugkeren:

{
        "_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")
}

Die het eerste document correct bovenaan de sorteervolgorde plaatst, rekening houdend met de "maxDate".




  1. Hoe kan ik de LIKE-operator op mangoest gebruiken?

  2. MongoDB-aggregatie met $ lookup omvat (of projecteert) alleen enkele velden die moeten worden geretourneerd uit de query

  3. Rdbtools bij Redis Conf18

  4. Afronding op 2 decimalen met behulp van het MongoDB-aggregatieraamwerk