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

条件付きで集約パイプラインステージを含める

    提供するオプションに応じて、パイプライン全体を構築することを意味します。結局のところ、これは単なるデータ構造です。

    また、「アレイ」を誤ってテストしているため、 instanceof typeof 実際には"object"を返します "array"ではありません 。

    さらに、最初のでその状態が本当に必要です の後に追加されるだけでなく、ドキュメントを最適に選択するためのパイプラインステージ $ unwind 必要な場合:

    var pipeline = [
      { $match: 
          Object.assign(
            { 'shop.nameSlug' : req.query.nameSlug },
            (req.query.status) 
              ? { "status.status": (req.query.status instanceof Array)
                ? { "$in": req.query.status } : req.query.status }
              : {}
          )
      },
      { $unwind: "$status" },
      ...(
        (req.query.status)
          ? [{ "$match": { 
              "status.status": (req.query.status instanceof Array)
               ? { "$in": req.query.status } : req.query.status
           }}]
          : []
        ),
        { $group: {
          _id: "$_id",
          status: { $addToSet: "$status" },
          number: { $first: "$number" },
          date: { $first: "$date" },
          comment: { $first: "$comment" }
        }}
    ];    
    
    
    Order.aggregate(pipeline).exec(function(err, orders){
    
    })
    

    与えられたreq statusに何かが存在するオブジェクト あなたが得る:

    // Example stucture
    var req = {
      query: { 
       nameSlug: "Bill", 
       status: "A"
      },
    };
    
    // Pipeline output as:
    
    [
        {
            "$match" : {
                "shop.nameSlug" : "Bill",
                "status.status" : "A"
            }
        },
        {
            "$unwind" : "$status"
        },
        {
            "$match" : {
                "status.status" : "A"
            }
        },
        {
            "$group" : {
                "_id" : "$_id",
                "status" : {
                    "$addToSet" : "$status"
                },
                "number" : {
                    "$first" : "$number"
                },
                "date" : {
                    "$first" : "$date"
                },
                "comment" : {
                    "$first" : "$comment"
                }
            }
        }
    ]
    

    配列を使用する場合:

    var req = {
      query: { 
       nameSlug: "Bill", 
       status: ["A","B"]
      },
    };
    
    // Pipeline output as:
    [
        {
            "$match" : {
                "shop.nameSlug" : "Bill",
                "status.status" : {
                    "$in" : [ 
                        "A", 
                        "B"
                    ]
                }
            }
        },
        {
            "$unwind" : "$status"
        },
        {
            "$match" : {
                "status.status" : {
                    "$in" : [ 
                        "A", 
                        "B"
                    ]
                }
            }
        },
        {
            "$group" : {
                "_id" : "$_id",
                "status" : {
                    "$addToSet" : "$status"
                },
                "number" : {
                    "$first" : "$number"
                },
                "date" : {
                    "$first" : "$date"
                },
                "comment" : {
                    "$first" : "$comment"
                }
            }
        }
    ]
    

    そして何もなしで:

    var req = {
      query: { 
       nameSlug: "Bill", 
       //status: ["A","B"]
      },
    };
    
    // Pipeline output as:
    [
        {
            "$match" : {
                "shop.nameSlug" : "Bill"
            }
        },
        {
            "$unwind" : "$status"
        },
        {
            "$group" : {
                "_id" : "$_id",
                "status" : {
                    "$addToSet" : "$status"
                },
                "number" : {
                    "$first" : "$number"
                },
                "date" : {
                    "$first" : "$date"
                },
                "comment" : {
                    "$first" : "$comment"
                }
            }
        }
    ]
    

    したがって、提供された値に応じて、パーツが条件付きで含まれている場所を確認できます。

    $filterの使用

    本当に $ filterを使用する必要があります 代わりにここに。 $ unwindよりもはるかに効率的です。 そして、あなたは本当に何もグループ化していません。本当に必要なのは、フィルター処理された配列だけです。条件付きで追加するのはこれだけです:

    var pipeline = [
      { $match: 
          Object.assign(
            { 'shop.nameSlug' : req.query.nameSlug },
            (req.query.status) 
              ? { "status.status": (req.query.status instanceof Array)
                ? { "$in": req.query.status } : req.query.status }
              : {}
          )
      },
      ...(
        (req.query.status)
          ? [{ "$addFields": { 
              "status": {
                "$filter": {
                  "input": "$status",
                  "cond": {
                    [(req.query.status instanceof Array) ? "$in" : "$eq"]:
                      [ "$$this.status", req.query.status ]
                  }
                }    
              }
           }}]
          : []
        )
    ];
    

    $ inから選択できます。 および $ eq 提供されるものに応じて、比較テスト用。オプションで、全体を $ setUnion> 結果に「セット」を使用することを「本当に意味する」場合。ただし、一般的には、配列から値を「フィルタリング」したいように見えます。

    単一の値に対する同じ期待を持って:

    var req = {
      query: { 
       nameSlug: "Bill", 
       //status: ["A","B"]
       status: "A"
      },
    };
    
    /* 1 */
    [
        {
            "$match" : {
                "shop.nameSlug" : "Bill",
                "status.status" : "A"
            }
        },
        {
            "$addFields" : {
                "status" : {
                    "$filter" : {
                        "input" : "$status",
                        "cond" : {
                            "$eq" : [ 
                                "$$this.status", 
                                "A"
                            ]
                        }
                    }
                }
            }
        }
    ]
    

    配列:

    var req = {
      query: { 
       nameSlug: "Bill", 
       status: ["A","B"]
      },
    };
    
    /* 1 */
    [
        {
            "$match" : {
                "shop.nameSlug" : "Bill",
                "status.status" : {
                    "$in" : [ 
                        "A", 
                        "B"
                    ]
                }
            }
        },
        {
            "$addFields" : {
                "status" : {
                    "$filter" : {
                        "input" : "$status",
                        "cond" : {
                            "$in" : [ 
                                "$$this.status", 
                                [ 
                                    "A", 
                                    "B"
                                ]
                            ]
                        }
                    }
                }
            }
        }
    ]
    

    または何もない:

    var req = {
      query: { 
       nameSlug: "Bill", 
       //status: ["A","B"]
      },
    };
    
    /* 1 */
    [
        {
            "$match" : {
                "shop.nameSlug" : "Bill"
            }
        }
    ]
    

    フィルタリングする必要がない場合は、追加のパイプラインステージを削除するだけです。




    1. MongoDBの配列にネストされたサブドキュメントを削除します

    2. 安全な挿入のためのPymongo権限の問題

    3. asyncawaitを使用したマングースfindById

    4. mongodbでジャーナルのサイズを制御する方法は?