sql >> Databasteknik >  >> NoSQL >> MongoDB

Dynamisk klibbig sortering i Mongo för ett enkelt värde eller lista

Kan inte återskapa ditt fel men du har några "stavfel" i din fråga så jag kan inte vara säker på vad du faktiskt har.

Men om du antar att du faktiskt arbetar med MongoDB 2.6 eller senare vill du förmodligen ha $setIntersection eller $setIsSubset operatörer snarare än $setUnion . Dessa operatorer antyder "matchande" innehåll i arrayen de jämförs med, där $setUnion kombinerar bara den medföljande arrayen med den befintliga:

db.people.aggregate([
    { "$project": {
        "first_name": 1,
        "last_name": 1,
        "sticky": { 
            "$size": { 
                "$setIntersection": [ "$offices", [ "FL", "SC" ]] 
            }
        },
        "offices": 1
    }},
    { "$sort": {
        "sticky": -1,
        "last_name": 1
    }}
])

I tidigare versioner där du inte har dessa uppsättningsoperatorer du använder bara $unwind att arbeta med arrayen, och samma sorts $cond drift som tidigare inom en $group för att få ihop allt igen:

db.people.aggregate([
    { "$unwind": "$offices" },
    { "$group": {
        "_id": "$_id",
        "first_name": { "$first": "$first_name" },
        "last_name": { "$first": "$last_name",
        "sticky": { "$sum": { "$cond": [
            { "$or": [
                { "$eq": [ "$offices": "FL" ] },
                { "$eq": [ "$offices": "SC" ] },
            ]},
            1,
            0
        ]}},
        "offices": { "$push": "$offices" }
    }},
    { "$sort": {
        "sticky": -1,
        "last_name": 1
    }}
])

Men du var verkligen på rätt väg. Välj bara rätt inställningsoperation eller annan metod för att få ditt exakta behov.

Eller eftersom du har publicerat ditt sätt att få det du vill ha, är ett bättre sätt att skriva den typen av "ordnad matchning" detta:

db.people.aggregate([
    { "$project": {
        "first_name": 1,
        "last_name": 1,
        "sticky": { "$cond": [
            { "$anyElementTrue": {
                "$map": {
                    "input": "$offices",
                    "as": "o",
                    "in": { "$eq": [ "$$o", "FL" ] }
                }
            }},
            2,
            { "$cond": [
                { "$anyElementTrue": {
                    "$map": {
                        "input": "$offices",
                        "as": "o",
                        "in": { "$eq": [ "$$o", "SC" ] }
                    }
                }},
                1,
                0
            ]}
        ]},
        "offices": 1
    }},
    { "$sort": {
        "sticky": -1,
        "last_name": 1
    }}
])

Och det skulle prioritera det dokument med "kontor" som innehåller "FL" över "SC" och därmed över alla andra, och göra operationen inom ett enda fält. Det borde också vara väldigt lätt för människor att se hur man abstraherar det till formuläret med $unwind i tidigare versioner utan de inställda operatorerna. Där du helt enkelt anger det högre "vikt"-värdet till objekten du vill ha överst genom att kapsla $cond uttalanden.



  1. Skriver du en fråga för att lägga till flera värden till en nyckel i REDIS-hashar?

  2. Lös DBRef till Json

  3. Varför får man ett felmeddelande när man uppdaterar MongoDb?

  4. Hur man konstruerar och skickar bson-dokument - Go lang?