有条件地包括聚合管道阶段

时间:2017-09-22 10:25:22

标签: javascript node.js mongodb aggregation-framework

我有一个函数可以根据给定的参数给我一些订单。 但是,参数可以为空,在这种情况下,我想单独留下void CFAROSDKDemoAppDlg::DoDataExchange(CDataExchange* pDX) { [...] DDX_Control(pDX, IDC_FOLDERBROWSER, m_FolderPathCtrl); [...] BEGIN_MESSAGE_MAP(CFAROSDKDemoAppDlg, CDialog) [...] ON_EN_CHANGE(IDC_FOLDERBROWSER, &CFAROSDKDemoAppDlg::OnEnChangeFolderbrowser) [...] BOOL CFAROSDKDemoAppDlg::OnInitDialog() { [...] if (::IsWindow(m_FolderPathCtrl.m_hWnd)) m_FolderPathCtrl.SetWindowText(m_FolderPath); // display the default path // m_FolderPathCtrl.EnableFolderBrowseButton(); [...] void CFAROSDKDemoAppDlg::OnEnChangeFolderbrowser() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here UpdateData(true); try { m_FolderPathCtrl.GetWindowText(m_FolderPath); } catch (...) { AfxMessageBox(L"Program failed to access this folder.", MB_OK | MB_ICONSTOP); } UpdateData(false); }

这是我目前的代码:

$id=mysqli_real_escape_string($link, htmlspecialchars($_GET['id'], ENT_QUOTES));
$id=preg_replace("/[^0-9]/", "", $id);

$match为null时,没有返回任何订单,因为mongo正在搜索等于null的字段。如何在if(req.query.status && typeof(req.query.status) == 'array'){ var match = { $in: req.query.status }; }else if(req.query.status){ var match = req.query.status; }else{ //when empty find all statuses var match = null; } Order.aggregate( { $match: { 'shop.nameSlug' : req.query.nameSlug, } }, { $unwind: "$status" }, { $match: { "status.status" : match } }, { $group: { _id: "$_id", status: { $addToSet: "$status" }, number: { $first: "$number" }, date: { $first: "$date" }, comment: { $first: "$comment" } } } ).exec(function(err, orders){ }) 时删除match

1 个答案:

答案 0 :(得分:3)

您的意思是根据提供的选项构建整个管道。它只是一种数据结构。

你也错误地测试了一个“数组”,你应该使用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"
        }
    }
]

如果您不需要过滤,那么您只需删除其他管道阶段。