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

Necessità di trovare il valore più frequente di un campo in un aggregato

Beh, non puoi semplicemente "truccarti". operatori come $mode non è un operatore di aggregazione e le uniche cose che puoi usare sono quelle che effettivamente esistono .

Quindi, per restituire il valore della categoria all'interno del periodo di tempo raggruppato che si verifica di più, è necessario raggruppare prima ciascuno di quei valori e restituire il conteggio delle occorrenze. Quindi puoi ordinare questi risultati in base a quel conteggio e restituire il valore della categoria che ha registrato il conteggio più alto in quel periodo:

    // Filter dates
    { "$match": { 
        "dt": { 
            "$gt": new Date("October 13, 2010 12:00:00"), 
            "$lt": new Date("November 13, 2010 12:00:00")
        } 
    }},

    // Group by hour and category, with avg and count
    { "$group": {
        "_id": {
            "dt": {
                "$add": [
                    {
                        "$subtract": [
                            { "$subtract": ["$dt", new Date(0)] },
                            {
                                "$mod": [
                                    { "$subtract": ["$dt", new Date(0)] },
                                    3600000//1000 * 60 * 60
                                ]
                            }
                        ]
                    },
                    new Date(0)
                ]
            },
            "category": "$category"
        }, 
        "price": { "$avg": "$price" },
        "count": { "$sum": 1 }
    }},
    // Sort on date and count
    { "$sort": { "_id.dt": 1, "count": -1 }},

    // Group on just the date, keeping the avg and the first category
    { "$group": {
        "_id": "$_id.dt",
        "price": { "$avg": "$price"}
        "category": { "$first": "$_id.category" }
    }}

Quindi $group sia sulla data che sulla categoria e conserva il conteggio delle categorie tramite $sum . Quindi $sort quindi il "conteggio" più grande è in cima a ciascuna data raggruppata. E infine usa $first quando applichi un altro $group che viene semplicemente applicato alla data stessa, in modo da restituire quella categoria con il conteggio più grande per ciascuna data.

Non lasciarti tentare da operatori come $max dato che non funzionano qui. La differenza fondamentale è la relazione "legata" al "record/documento" prodotto per ogni valore di categoria. Quindi non è il massimo "conteggio" desiderato o il valore massimo di "categoria", ma invece il valore della categoria che "ha prodotto" il conteggio più grande. Quindi c'è un $sort necessario qui.

Finalmente alcune abitudini che "dovresti" rompere:

  • Non utilizzare dati di istanza di data in formato non UTC come input a meno che tu non sappia davvero cosa stai facendo. Le date verranno sempre convertite in UTC, quindi almeno negli elenchi di test dovresti abituarti a specificare il valore della data in questo modo.

  • Potrebbe sembrare un po' più pulito nell'altro modo, ma cose come 1000 * 60 * 60 sono un codice molto più descrittivo di ciò che sta facendo rispetto a 3600000 . Stesso valore, ma una forma è indicativa delle sue unità di tempo a colpo d'occhio.

  • _id composto quando c'è un solo valore può anche confondere i problemi. Quindi non ha molto senso accedere a _id.dt se quello fosse l'unico valore presente. When è più di una singola proprietà all'interno di _id allora va bene. Ma i valori singoli dovrebbero essere semplicemente assegnati di nuovo a _id solo. Niente guadagnato altrimenti, e il singolo è abbastanza chiaro.