MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Ogranicz agregację w agregacji zgrupowanej

Ponieważ Twoje pytanie jest obecnie niejasne, naprawdę mam nadzieję, że chcesz określić dwie Site klawisze i 2 Software klucze, ponieważ jest to ładna i prosta odpowiedź, którą możesz po prostu dodać do fazy $match, jak w:

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

I wszyscy możemy kibicować i być szczęśliwym;)

Jeśli jednak twoje pytanie jest bardziej diaboliczne, takie jak uzyskanie 2 najlepszych Sites i Software wpisy z wyniku według czasu trwania, a następnie bardzo dziękujemy za pojawienie się tej obrzydliwości .

Ostrzeżenie:

Twój przebieg może się różnić w zależności od tego, co faktycznie chcesz zrobić, lub od tego, czy będzie to wysadzić w powietrze przez sam rozmiar twoich wyników. Ale to jest przykład tego, na co cię czeka:

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}

])  

Wynikiem tego jest *niezupełnie czysty zestaw wyników, który byłby idealny, ale jest to coś, z czym można pracować programowo i jest to lepsze niż filtrowanie poprzednich wyników w pętli. (Moje dane z testów)

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

Widzisz, że otrzymujesz 2 najlepsze Sites w tablicy, z górnymi dwoma Software elementy osadzone w każdym. Sama agregacja nie może już tego wyjaśnić, ponieważ musielibyśmy ponownie połączyć elementy, które podzieliliśmy, aby to zrobić, a jak dotąd nie ma operatora, którego moglibyśmy użyć do wykonania tej czynności.

Ale to było zabawne. To nie wszystko sposób, ale większość drogi, a zrobienie z tego odpowiedzi na 4 dokumenty byłoby stosunkowo trywialnym kodem. Ale już mnie boli głowa.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Atomowa aktualizacja MongoDB za pomocą dokumentu „scal”

  2. Usuń określony zagnieżdżony obiekt z tablicy obiektów

  3. Klucz złożony MongoDB:InvalidOperationException:{document}. Tożsamość nie jest obsługiwana

  4. Utknąłem w ładowaniu z mangustą?

  5. Jak przechowywać zamówiony zestaw dokumentów w MongoDB bez używania ograniczonej kolekcji?