2
votes

Comment trouver des documents consécutifs avec nombre dans MongoDB?

J'ai une collection de messages reçus d'utilisateurs. Je veux le regrouper par séquence consécutive de userName triée par horodatage. J'ai des messages de collection comme mentionné ci-dessous:

{
    "userName":"Krunal",
    "count":3,
    "timestamp":ISODate("2019-06-17T12:05:00.000")
}
{
    "userName":"Karan",
    "count":2,
    "timestamp":ISODate("2019-06-17T12:10:00.000")
}
{
    "userName":"Krunal",
    "count":1,
    "timestamp":ISODate("2019-06-17T12:12:00.000")
}

J'utilise un identifiant d'objet de 4 octets pour le rendre facile à lire, dans un scénario réel, ce sera l'identifiant d'objet réel généré par mongodb De la collection ci-dessus, je veux une sortie comme mentionné ci-dessous:

{
    "_id":ObjectId("AAAA")
    "userName":"Krunal"
    "message":"Krunal types some text",
    "timestamp":ISODate("2019-06-17T11:57:00.000")
}
{
    "_id":ObjectId("AAAB")
    "userName":"Krunal"
    "message":"Krunal types some text again",
    "timestamp":ISODate("2019-06-17T11:59:00.000")
}
{
    "_id":ObjectId("AAAC")
    "userName":"Krunal"
    "message":"Krunal types some text one more time",
    "timestamp":ISODate("2019-06-17T12:05:00.000")
}
{
    "_id":ObjectId("AAAD")
    "userName":"Karan"
    "message":"Karan type some text",
    "timestamp":ISODate("2019-06-17T12:07:00.000")
}
{
    "_id":ObjectId("AAAE")
    "userName":"Karan"
    "message":"Karan type some more text",
    "timestamp":ISODate("2019-06-17T12:10:00.000")
}
{
    "_id":ObjectId("AAAC")
    "userName":"Krunal"
    "message":"Krunal types some text one more time",
    "timestamp":ISODate("2019-06-17T12:12:00.000")
}

Je veux compter les messages consécutifs de l'utilisateur avec userName Y a-t-il une requête disponible dans mongodb à utiliser ou j'ai besoin d'écrire un algorithme séparé après une simple requête de recherche?

MODIFIER: Je ne souhaite pas regrouper uniquement par nom d'utilisateur. je veux est groupé par userName avec des documents consécutifs. Par exemple, compte tenu de la collection susmentionnée. Krunal a envoyé 3 messages consécutivement donc Krunal: 3, puis Karan a envoyé 2 messages consécutivement donc Karan: 2, Maintenant Krunal a envoyé un message de plus mais après karan donc ce sera un nouvel objet comme Krunal: 1, Ce ne sera pas incrémenter le décompte précédent de Krunal


0 commentaires

3 Réponses :


0
votes

Utilisez ceci.

db.collection.aggregate([{"$group": {"_id":"$userName","count": {$sum:1},"timestamp": {"$first": "$$ROOT.timestamp"}}}])


1 commentaires

Merci pour votre réponse, mais cela me donnera le nombre de messages pour chaque nom d'utilisateur. Je veux la même chose avec la séparation des documents consécutifs. J'ai inclus la sortie attendue dans ma requête



0
votes
db.collection.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $group: {
                _id: '$userName',
                count: {
                    $sum: 1
                },
                timestamp: {
                    $last: '$timestamp'
                }

            }
        },

        // Stage 2
        {
            $project: {
                userName: '$_id',
                count: 1,
                timestamp: 1,
                _id: 0
            }
        },

    ]



);

0 commentaires

3
votes

C'est la solution que j'ai trouvée.

Ce n'est pas une seule requête agrégée mais je suis en train d'itérer sur chaque entrée en utilisant une boucle forEach dans un script mongo (fichier Javascript qui peut être exécuté avec mongo).

[{"userName":"Krunal","count":3,"timestamp":"2019-06-17T12:05:00.000Z"},{"userName":"Karan","count":2,"timestamp":"2019-06-17T12:10:00.000Z"},{"userName":"Krunal","count":1,"timestamp":"2019-06-17T12:12:00.000Z"}]

Résultat:

var prev_name = "";
var count = 0;
var obj_dict = {};
var entries = [];
var prev_timestamp;

db.wikidata.find().forEach(function(entry) {
    var name = entry["userName"];
    if(prev_name === ""){
        count += 1;
        prev_name = name;
        prev_timestamp = entry["timestamp"];
    } else if(prev_name === name){
        count += 1;
        prev_timestamp = entry["timestamp"];
    } else {
        obj_dict["userName"] = prev_name;
        obj_dict["count"] = count;
        obj_dict["timestamp"] = prev_timestamp;
        entries.push(obj_dict);
        prev_name = name;
        count = 1;
        prev_timestamp = entry["timestamp"];
        obj_dict = {};
    }
})

obj_dict["userName"] = prev_name;
obj_dict["count"] = count;
obj_dict["timestamp"] = prev_timestamp;
entries.push(obj_dict);

print(JSON.stringify(entries));

J'espère que cela vous aidera.


1 commentaires

Merci @Shubham Vaishnav pour votre réponse. Oui, cela peut être fait en utilisant le post-traitement mais je cherche si cela peut être fait uniquement en utilisant la requête mongodb