Как найти последовательные документы с подсчетом в MongoDB? - PullRequest
1 голос
/ 17 июня 2019

У меня есть коллекция сообщений, полученных от пользователей. Я хочу сгруппировать его по последовательной последовательности userName, отсортированной по метке времени. У меня есть сообщения о сборе, как указано ниже:

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

Я использую 4-байтовый идентификатор объекта, чтобы его было легко читать. В реальном сценарии это будет фактический идентификатор объекта, сгенерированный mongodb. Из вышеприведенной коллекции я хочу вывод, как указано ниже:

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

Я хочу посчитать количество последовательных сообщений от пользователя с именем пользователя Есть ли в Mongodb какой-либо запрос для использования, или мне нужно написать отдельный алгоритм после простого запроса поиска?

EDIT: Я не хочу группировать только по имени пользователя. Я хочу, чтобы сгруппированы по userName с последовательными документами. Например, учитывая вышеупомянутую коллекцию. Крунал отправил 3 сообщения последовательно, так что Крунал: 3, затем Каран отправил 2 сообщения последовательно, поэтому Каран: 2, Теперь Крунал отправил еще одно сообщение, но после Карана это будет новый объект как Крунал: 1, Не будет увеличить предыдущий счет Крунала

Ответы [ 3 ]

0 голосов
/ 17 июня 2019
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 голосов
/ 25 июня 2019

Это решение, которое я придумал.

Это не один агрегатный запрос, но вместо этого я перебираю каждую запись, используя цикл forEach в скрипте Монго (файл Javascript, который может быть выполнен с Монго).

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));

Выход:

[{"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"}]

Надеюсь, это поможет.

0 голосов
/ 17 июня 2019

Используйте это.

db.collection.aggregate([{"$group": {"_id":"$userName","count": {$sum:1},"timestamp": {"$first": "$$ROOT.timestamp"}}}])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...