MongoDB - агрегировать по отдельным полям, а затем считать в день - PullRequest
0 голосов
/ 21 января 2019

У меня есть база данных mongodb, которая собирает данные об устройстве. Пример документа

{
    "_id" : ObjectId("5c125a185dea1b0252c5352"),
    "time" : ISODate("2018-12-13T15:09:42.536Z"),
    "mac" : "10:06:21:3e:0a:ff",
}

Цель состоит в том, чтобы подсчитывать уникальные значения mac в день, от первого документа в БД до последнего документа в БД.

Я поиграл и пришел к выводу, что мне нужно иметь несколько групп, а также проекты во время агрегации.

Это то, что я пытался - не уверен, в правильном ли направлении или нет, или просто полностью запутался.

   pipeline = [
        {"$project": {
            "_id": 1,
            "mac": 1,
            "day": {
                "$dayOfMonth":"$time"
            },
            "month": {
                "$month":"$time"
            },
            "year": {
                "$year":"$time"
            }
        }
        },
        {
        "$project": {
            "_id": 1,
            "mac": 1,
            "time": {
                "$concat": [{
                    "$substr":["$year", 0, 4]
                },
                "-", {
                    "$substr": ["$month", 0, 2]

                },
                "-",
                {
                    "$substr":["$day", 0, 2]
                }]
                }
            }
        },
        {
            "$group": {
                "_id": {
                    "time": "$time",
                    "mac": "$mac"
                }
            },
            "$group": {
                "_id": "$_id.time",
                "count":{"$sum": 1},
            }
        }
    ]

    data = list(collection.aggregate(pipeline, allowDiskUse=True))

Вывод теперь не похож на агрегацию,

[{"_id": null, "count": 751050}]

Я использую Pymongo в качестве драйвера и использую Mongodb 4.

В идеале он должен просто показывать дату и количество (например, {"_id": "2018-12-13", "count": 2}.

Я хотел бы получить отзывы и советы. Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 21 января 2019
[
                {
            "$project": {
                "_id": 1,
                "mac": 1,
                "time": { "$dateToString": { "format": "%Y-%m-%d", "date": "$time", "timezone": "Africa/Johannesburg"}}
            },
        },

        {
            "$group": {
                "_id":{
                "time": "$time",
                "mac": "$mac",
            }}},{
            "$group": {
                "_id": "$_id.time",
                "count":{"$sum": 1}
            }},
         {"$sort": SON([("_id", -1)])}

]

Делает именно то, что должен делать.Благодарю.:)

0 голосов
/ 22 января 2019

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

pipeline = [ 
  { '$group' : {
      '_id': { '$dateToString': { 'format': "%Y-%m-%d", 'date': "$time" } },
      'macs':{ '$addToSet': '$mac' }
   } },
   {$addFields:{ 'macs':{'$size':'$macs'}}}
]
0 голосов
/ 21 января 2019

Есть оператор с именем $ dateToString, который решит большинство ваших проблем.

Редактировать: Не читал вопрос внимательно, @Ася Камский, спасибо, что указали. Вот новый ответ.

  pipeline = [
  {
    "$group": {
      "_id": {
        "date": {
          $dateToString: {
            format: "%Y-%m-%d",
            date: "$time"
          }
        },
        "mac": "$mac"
      }
    }
  },
  {
    "$group": {
      "_id": "$_id.date",
      "count": {
        "$sum": 1
      }
    }
  }
]
...