2017-02-18 98 views
2

我在mongodb聚合中有匹配表达式。比赛中包含3个字段,但并不总是包含数据。如果该字段不为空,我只想在匹配中包含这些字段。如何动态构建mongodb查询

这就是匹配的样子,如果所有的字段都有数据,但是例如,如果用于studentGradeLevels的数组为空,那么我不想包含它,或者我希望查询仍然返回数据而忽略空的参数。

$match: { 
    "school._id": "7011", 
    "studentGradeLevels": { $in: ["09", "10", "11", "12"] }, 
    "contentArea": { 
     $in: [ 
      "English 1" 
     ] 
    } 
} 

有没有办法要么动态地构建了比赛,这样我只包括基于它们是否为空或不或做一些查询,以便是空的参数被忽略我想要的字段。

回答

2

您可以使用$in当数组不为空,并$nin当数组是空的,这样的比赛场将不被考虑在内($nin : []):

function buildMatch(arr) { 
    var matcher = {}; 
    if (arr.length == 0) 
     matcher["$nin"] = arr; 
    else 
     matcher["$in"] = arr; 
    return matcher; 
} 

var grades = ["09", "10", "11", "12"]; 
var areas = [ "English 2" ]; 

var gradeMatch = buildMatch(grades); 
var areaMatch = buildMatch(areas); 

db.students.aggregate([{ 
    $match: { 
     "school._id": "7011", 
     "studentGradeLevels": gradeMatch, 
     "contentArea": areaMatch 
    } 
}]) 
+0

看起来像这样回答“如果我的查询参数为空,该怎么办”。我认为OP想要这样做:“如果我查询contentArea和schoolGradeLevels,并且候选文档都设置了这两个字段,则尝试匹配,但是如果例如schoolGradeLevels没有设置在候选人中,那么甚至不要尝试匹配该字段;只是尝试匹配contentArea。“ –

0

的变化:检查字段是否存在,如果是的话,改为一个特殊的价值,例如_并将其添加到$in列表中:

db.foo.aggregate([ 
{$project: {"studentGradeLevels":{$ifNull: ["$studentGradeLevels","_"]}, 
      "contentArea":{$ifNull: ["$contentArea","_"]} 
}} 
,{$match: { 
     "studentGradeLevels": { $in: ["_", "09", "10", "11", "12"] }, 
     "contentArea": { $in: [ "_", "English 1" ] } 
}} 
       ]);