sql >> Databáze >  >> NoSQL >> MongoDB

Omezit agregaci ve seskupené agregaci

Vzhledem k tomu, že vaše otázka je v současné době nejasná, opravdu doufám, že chcete uvést dvě Site klíče a 2 Software klíčů, protože to je hezká a jednoduchá odpověď, kterou můžete přidat do své $match fáze jako v:

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

A všichni můžeme fandit a být šťastní;)

Pokud je však vaše otázka něco ďábelštějšího, například získání 2 nejlepších Sites a Software zápisy z výsledku podle trvání, pak vám moc děkujeme za zplození této ohavnosti .

Upozornění:

Váš počet najetých kilometrů se může lišit v závislosti na tom, co skutečně chcete dělat, nebo zda to bude vybouchnout podle pouhé velikosti vašich výsledků. Ale toto následuje jako příklad toho, co vás čeká:

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}

])  

Nyní to má za následek *není přesně čistá sada výsledků, která by byla ideální, ale je to něco, s čím lze programově pracovat a je to lepší než filtrování předchozích výsledků ve smyčce. (Moje data z testování)

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

Takže vidíte, že máte 2 nejlepší Sites v poli, s horními 2 Software položky vložené do každého z nich. Samotná agregace to nemůže dále objasnit, protože bychom museli znovu sloučit položky, které jsme za tímto účelem rozdělili, a zatím neexistuje žádný operátor, který bychom mohli použít k provedení této akce.

Ale byla to zábava. Není to vše tak, jak se to dělá, ale většina a vytvořit z toho odpověď se 4 dokumenty by byl relativně triviální kód. Ale už mě bolí hlava.




  1. Jak implementovat multitenancy pro redis v jarním bootování

  2. Meteor předává ID do odkazu

  3. Jarní bota + redis

  4. Dotaz MongoDB na vyplněná pole