Bagaimana cara mengelompokkan elemen selanjutnya di mongo?

Bagaimana saya bisa mengelompokkan elemen berikutnya berdasarkan properti di mongo. Ini adalah dokumen mongo saya (Acara) dan saya ingin dapat mengelompokkannya secara berurutan berdasarkan jenisnya.

{
    "_id" : ObjectId("5d1b68d708f3870049d9cc37"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "76800453-e72e-410b-accc-cf47cd2773a1",
    "type" : "controller_connection_status",
    "timestamp" : 1562077399832.0,

}

/* 2 */
{
    "_id" : ObjectId("5d1b68db08f3870049d9cc39"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "fabd883c-6971-4977-b3fc-31679c2b85dd",
    "type" : "controller_connection_status",
    "timestamp" : 1562077402916.0,
}

/* 3 */
{
    "_id" : ObjectId("5d1b68db08f3870049d9cc3a"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "siteId" : "226168be-866c-11e8-adc0-fa7ae01bbebc",
    "id" : "98decbea-8288-4df5-807d-14e90f929df2",
    "type" : "controller_added",
    "timestamp" : 1562077402920.0,
}

/* 4 */
{
    "_id" : ObjectId("5d1b690908f3870049d9cc3c"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "b5ad6199-8805-43fd-bd7e-80f0410e744a",
    "type" : "controller_connection_status",
    "timestamp" : 1562077449904.0,
}

/* 5 */
{
    "_id" : ObjectId("5d1b690d08f3870049d9cc3d"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "276ea325-0eec-47a2-8e0e-3805ed34b80b",
    "type" : "controller_error",
    "timestamp" : 1562077452975.0,
}

/* 6 */
{
    "_id" : ObjectId("5d1b694508f3870049d9cc3f"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "03ce803b-6b2e-49fe-8f0d-4feee44251e9",
    "type" : "controller_error",
    "timestamp" : 1562077509904.0,
}

/* 7 */
{
    "_id" : ObjectId("5d1b694908f3870049d9cc41"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "b144a04f-8201-4945-b2c4-faef5b41866e",
    "type" : "controller_connection_status",
    "timestamp" : 1562077512974.0,
}

/* 8 */
{
    "_id" : ObjectId("5d1b698208f3870049d9cc42"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "235874f3-c017-4ea8-abaf-8c5edf1b317a",
    "type" : "controller_connection_status",
    "timestamp" : 1562077569903.0,
}

/* 9 */
{
    "_id" : ObjectId("5d1b698508f3870049d9cc43"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "4fb3706f-d195-4ded-87b9-8482c712825c",
    "type" : "controller_connection_status",
    "timestamp" : 1562077572973.0,
    "createdAt" : ISODate("2019-07-02T14:26:13.120Z"),
    "updatedAt" : ISODate("2019-07-02T14:26:13.120Z"),
    "__v" : 0
}

/* 10 */
{
    "_id" : ObjectId("5d1b69bd08f3870049d9cc45"),
    "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
    "id" : "e743baef-1701-436a-baf2-8367a0917c81",
    "type" : "controller_removed",
    "timestamp" : 1562077629903.0,
}

Hasil yang saya inginkan:

timestamp         type                                               count
(last timestamp)  controller_connection_status                         2
 --               controller_added                                     1
 --               controller_connection_status                         1
 --               controller_error                                     2
 --               controller_connection_status                         3
 --               controller_removed                                   1

Apa yang saya coba sejauh ini:

db.getCollection('events').aggregate([
      {
        '$match': {
          'controllerId': '80058c2b-9525-4f7f-8e26-faea4ad92b15'
        }
      },
      {
        '$group': {
          '_id': '$type',
          'type': {
            '$first': '$type'
          },
          'timestamp': {
            '$last': '$timestamp'
          },
          'count': {
            '$sum': 1,
          }
        }
      },
      {
        '$sort': {
          'timestamp': -1
        }
      }
])

Keluaran saya:

timestamp         type                                               count
(last timestamp)  controller_connection_status                         6
 --               controller_added                                     1
 --               controller_error                                     2
 --               controller_removed                                   1

person raven    schedule 08.07.2019    source sumber
comment
Lihatlah stackoverflow.com/questions/55606445/ Jika pertanyaan saya benar, Anda ingin mendeteksi perubahan type dalam dokumen berturut-turut. Satu-satunya perbedaan adalah Anda perlu menambahkan jumlah dan stempel waktu maksimal.   -  person Alex Blex    schedule 08.07.2019


Jawaban (1)


Anda dapat menggunakan $graphLookup untuk mengelompokkan dokumen berurutan ke dalam array. Ini memerlukan koleksi untuk dicari dan dalam kasus Anda itu bisa berupa view.

Tampilan ini menggabungkan dokumen dalam pasangan sebelumnya-berikutnya menggunakan operator $zip :

db.createView("events-view", "original_collection", [
    { $sort: { timestamp: 1 } },
    { $group: { _id: null, docs: { $push: "$$ROOT" } } },
    { $project: {
        pair: { $zip: {
            inputs:[ { $concatArrays: [ [false], "$docs" ]} , "$docs" ]            
        } }
    } },
    { $unwind: "$pair" },
    { $project: {
        prev: { $arrayElemAt: [ "$pair", 0 ] },
        next: { $arrayElemAt: [ "$pair", 1 ] }
    } },
    { $project: {
        _id: "$prev._id",
        prev: 1,
        next: 1,
        sameType: { $eq: ["$prev.type", "$next.type"] } 
    } },
]);

Seharusnya terlihat seperti berikut:

{
    "prev" : false,
    "next" : {
        "_id" : ObjectId("5d1b68d708f3870049d9cc37"),
        "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
        "id" : "76800453-e72e-410b-accc-cf47cd2773a1",
        "type" : "controller_connection_status",
        "timestamp" : 1562077399832.0
    },
    "sameType" : false
},
{
    "prev" : {
        "_id" : ObjectId("5d1b68d708f3870049d9cc37"),
        "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
        "id" : "76800453-e72e-410b-accc-cf47cd2773a1",
        "type" : "controller_connection_status",
        "timestamp" : 1562077399832.0
    },
    "next" : {
        "_id" : ObjectId("5d1b68db08f3870049d9cc39"),
        "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
        "id" : "fabd883c-6971-4977-b3fc-31679c2b85dd",
        "type" : "controller_connection_status",
        "timestamp" : 1562077402916.0
    },
    "_id" : ObjectId("5d1b68d708f3870049d9cc37"),
    "sameType" : true
},
{
    "prev" : {
        "_id" : ObjectId("5d1b68db08f3870049d9cc39"),
        "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
        "id" : "fabd883c-6971-4977-b3fc-31679c2b85dd",
        "type" : "controller_connection_status",
        "timestamp" : 1562077402916.0
    },
    "next" : {
        "_id" : ObjectId("5d1b68db08f3870049d9cc3a"),
        "controllerId" : "80058c2b-9525-4f7f-8e26-faea4ad92b15",
        "siteId" : "226168be-866c-11e8-adc0-fa7ae01bbebc",
        "id" : "98decbea-8288-4df5-807d-14e90f929df2",
        "type" : "controller_added",
        "timestamp" : 1562077402920.0
    },
    "_id" : ObjectId("5d1b68db08f3870049d9cc39"),
    "sameType" : false
},
etc...

Kemudian Anda dapat menanyakan tampilan yang mengelompokkan dokumen berdasarkan jenis dan stempel waktu terbaru hingga kondisi "sameType" berlaku. Rantai dokumen terpanjang adalah jumlah yang Anda cari:

db.getCollection("events-view").aggregate([
   { $graphLookup: {
       from: "events-view",
       startWith: "$next._id",
       connectFromField: "next._id",
       connectToField: "_id",
       restrictSearchWithMatch: { "sameType": true },
       as: "chain"
   } },
   { $project: {
       _id: "$next._id",
       type: "$next.type",
       chain: { $concatArrays: [ [{ next: "$next" }], "$chain" ] }
   } },
   { $addFields: {
       chainLength: { $size: "$chain" },
       timestamp: { $max: { $map: {
           input: "$chain",
           in: "$$this.next.timestamp"
       } } }
   } },
   { $group: {
       _id: {type: "$type", timestamp: "$timestamp"},
       count: {$max: "$chainLength"}
   } },
   { $sort: { "_id.timestamp": 1 } }, 
   { $project: {
       _id: 0,
       timestamp: "$_id.timestamp",
       type: "$_id.type",
       count: 1
   } }
])

Perlu disebutkan bahwa kuerinya akan sangat lambat. Semakin panjang rantai, semakin buruk kinerjanya. Perlu diingat juga bahwa tahap $graphLookup harus tetap berada dalam batas memori 100 megabita. Untuk koleksi yang lebih besar, Anda harus menyetel opsi allowDiskUse ke true.

person Alex Blex    schedule 12.07.2019