sql >> Database teknologi >  >> NoSQL >> MongoDB

Begræns aggregering i grupperet aggregering

Da dit spørgsmål i øjeblikket er uklart, håber jeg virkelig, at du mener, at du vil angive to Site nøgler og 2 Software nøgler, fordi det er et fint og enkelt svar, som du bare kan tilføje til din $match-fase som i:

{$match: {
    group_id: "20ea74df4f7074b33b520000",
    tracked_item_name: {$in: ['Twitter', 'Facebook', 'Word', 'Excel' ] }
}},

Og vi kan alle juble og være glade;)

Hvis dit spørgsmål er noget mere djævelsk, såsom at få de 2 bedste Sites og Software poster fra resultatet efter varighed, så takker vi dig meget for at skabe denne vederstyggelighed .

Advarsel:

Dit kilometertal kan variere afhængigt af, hvad du rent faktisk vil gøre, eller om dette vil sprænge i vejret på grund af størrelsen af ​​dine resultater. Men dette følger som et eksempel på, hvad du går efter:

db.collection.aggregate([

    // Match items first to reduce the set
    {$match: {group_id: "20ea74df4f7074b33b520000" }},

    // Group on the types and "sum" of duration
    {$group: {
        _id: {
            tracked_item_type: "$tracked_item_type",
            tracked_item_name: "$tracked_item_name"
         },
         duration: {$sum: "$duration"}
    }},

    // Sort by type and duration descending
    {$sort: { "_id.tracked_item_type": 1, duration: -1 }},

    /* The fun part */

    // Re-shape results to "sites" and "software" arrays 
    {$group: { 
        _id: null,
        sites: {$push:
            {$cond: [
                {$eq: ["$_id.tracked_item_type", "Site" ]},
                { _id: "$_id", duration: "$duration" },
                null
            ]}
        },
        software: {$push:
            {$cond: [
                {$eq: ["$_id.tracked_item_type", "Software" ]},
                { _id: "$_id", duration: "$duration" },
                null
            ]}
        }
    }},


    // Remove the null values for "software"
    {$unwind: "$software"},
    {$match: { software: {$ne: null} }},
    {$group: { 
        _id: "$_id",
        software: {$push: "$software"}, 
        sites: {$first: "$sites"} 
    }},

    // Remove the null values for "sites"
    {$unwind: "$sites"},
    {$match: { sites: {$ne: null} }},
    {$group: { 
        _id: "$_id",
        software: {$first: "$software"},
        sites: {$push: "$sites"} 
    }},


    // Project out software and limit to the *top* 2 results
    {$unwind: "$software"},
    {$project: { 
        _id: 0,
        _id: { _id: "$software._id", duration: "$software.duration" },
        sites: "$sites"
    }},
    {$limit : 2},


    // Project sites, grouping multiple software per key, requires a sort
    // then limit the *top* 2 results
    {$unwind: "$sites"},
    {$group: {
        _id: { _id: "$sites._id", duration: "$sites.duration" },
        software: {$push: "$_id" }
    }},
    {$sort: { "_id.duration": -1 }},
    {$limit: 2}

])  

Hvad det resulterer i er *ikke ligefrem det rene sæt af resultater, der ville være ideelt, men det er noget, der kan arbejdes programmæssigt med, og bedre end at filtrere de tidligere resultater i en loop. (Mine data fra test)

{
    "result" : [
        {
            "_id" : {
                "_id" : {
                    "tracked_item_type" : "Site",
                    "tracked_item_name" : "Digital Blasphemy"
                 },
                 "duration" : 8000
            },
            "software" : [
                {
                    "_id" : {
                        "tracked_item_type" : "Software",
                        "tracked_item_name" : "Word"
                    },
                    "duration" : 9540
                },

                {
                    "_id" : {
                        "tracked_item_type" : "Software",
                        "tracked_item_name" : "Notepad"
                    },
                    "duration" : 4000
                }
            ]
        },
        {
            "_id" : {
                "_id" : {
                    "tracked_item_type" : "Site",
                    "tracked_item_name" : "Facebook"
                 },
                 "duration" : 7920
            },
            "software" : [
                {
                    "_id" : {
                        "tracked_item_type" : "Software",
                         "tracked_item_name" : "Word"
                    },
                    "duration" : 9540
                },
                {
                    "_id" : {
                        "tracked_item_type" : "Software",
                        "tracked_item_name" : "Notepad"
                    },
                    "duration" : 4000
                }
            ]
        }
    ],
    "ok" : 1
}

Så du kan se, at du får de 2 bedste Sites i arrayet med de øverste 2 Software elementer indlejret i hver. Selve aggregationen kan ikke opklare dette yderligere, fordi vi ville være nødt til at gensammensmelte elementerne deler vi ad for at gøre dette, og endnu er der ingen operatør, som vi kan bruge til at udføre denne handling.

Men det var sjovt. Det er ikke alt måden gjort, men de fleste af vejen, og at gøre det til et svar på 4 dokumenter ville være relativt triviel kode. Men mit hoved gør allerede ondt.




  1. Fjernelse af database.yml ved brug af Mongoid i Rails 3.2

  2. mongodb, pymongo, aggregat giver mærkeligt output (noget om markøren)

  3. mongodb aggregering om opdatering af samlinger

  4. Sådan konfigureres fjederstartwebapp med redis ved hjælp af Docker