sql >> データベース >  >> NoSQL >> MongoDB

グループ化された集計で集計を制限する

    あなたの質問は現在不明であるため、2つのSiteを指定することを意味していることを願っています。 キーと2つのSoftware キーは、次のように$matchフェーズに追加できる素晴らしくシンプルな答えだからです。

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

    そして、私たちは皆、応援して幸せになることができます;)

    ただし、質問がもっと悪魔的なものである場合、たとえば、上位2つのSiteを取得する およびSoftware 期間ごとの結果からのエントリ、そしてこの忌まわしきを生み出してくれてありがとう 。

    警告:

    あなたのマイレージはあなたが実際にやりたいことや、これがあなたの結果の大きさによって爆発するかどうかによって変わるかもしれません。しかし、これはあなたが何を求めているかの例として続きます:

    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}
    
    ])  
    

    その結果、*正確にはなりません。 理想的な結果のクリーンなセットですが、プログラムで処理できるものであり、前の結果をループでフィルタリングするよりも優れています。 (テストからの私のデータ)

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

    つまり、上位2つのSiteを取得していることがわかります。 アレイ内で、上位2つのSoftware それぞれに埋め込まれたアイテム。 再マージする必要があるため、アグリゲーション自体はこれ以上これをクリアできません。 これを行うために分割したアイテムですが、このアクションを実行するために使用できる演算子はまだありません。

    でもそれは楽しかったです。 すべてではありません 方法は完了しましたが、ほとんど 方法の、そしてそれを4つのドキュメントの応答にすることは比較的簡単なコードです。しかし、私の頭はすでに痛いです。




    1. Mongoで、アトミック操作のようなチェックと設定を行う方法はありますか?

    2. コレクションを取得し、応答に値を追加します

    3. 可変日付で部分インデックスを作成するにはどうすればよいですか?

    4. Django ORMをmongoアトラスに接続する方法は?