MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Besoin de trouver la valeur la plus fréquente d'un champ dans un agrégat

Eh bien, vous ne pouvez pas simplement vous "maquiller". opérateurs comme $mode n'est pas un opérateur d'agrégation, et les seules choses que vous pouvez utiliser sont ceux qui existent réellement .

Ainsi, afin de renvoyer la valeur de catégorie dans la période de temps groupée qui se produit le plus, il est nécessaire de grouper d'abord sur chacune de ces valeurs et de renvoyer le nombre d'occurrences. Ensuite, vous pouvez trier ces résultats en fonction de ce nombre et renvoyer la valeur de catégorie qui a enregistré le nombre le plus élevé au cours de cette période :

    // 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" }
    }}

Donc $group sur la date et la catégorie et conserver le nombre de catégories via $sum . Ensuite, vous $sort donc le plus grand "compte" est en haut pour chaque date groupée. Et enfin, utilisez $first lorsque vous appliquez un autre $group qui est juste appliqué à la date elle-même, afin de renvoyer cette catégorie avec le plus grand nombre pour chaque date.

Ne vous laissez pas tenter par des opérateurs comme $max car ils ne travaillent pas ici. La principale différence est la relation "liée" au "record/document" produit pour chaque valeur de catégorie. Ce n'est donc pas le "nombre" maximal que vous voulez ou la valeur maximale de la "catégorie", mais plutôt la valeur de la catégorie qui "a produit" le plus grand nombre. Il existe donc un $sort nécessaire ici.

Enfin quelques habitudes que vous "devriez" casser :

  • N'utilisez pas de données d'instance de date au format non UTC comme entrée, sauf si vous savez vraiment ce que vous faites. Les dates seront toujours converties en UTC, donc au moins dans les listes de test, vous devriez vous habituer à spécifier la valeur de date de cette façon.

  • Cela peut sembler un peu plus propre dans l'autre sens, mais des choses comme 1000 * 60 * 60 sont un code beaucoup plus descriptif de ce qu'il fait que 3600000 . Même valeur, mais un formulaire indique ses unités de temps en un coup d'œil.

  • Composé _id lorsqu'il n'y a qu'une seule valeur peut également confondre les problèmes. Il est donc inutile d'accéder à _id.dt si c'était la seule valeur présente. Quand y a-t-il plus d'une seule propriété dans _id alors c'est bon. Mais les valeurs uniques doivent simplement être attribuées directement à _id seul. Rien de gagné autrement, et le single est assez clair.