MongoDB对缺少值的嵌套文档中的字段进行排序

时间:2019-07-22 21:20:00

标签: arrays mongodb

输入样本数据

/* 1 */
{  "name" : "alice",
    "attibutes" : [ 
        { "key" : "marks", "value" : 10 }, 
        { "key" : "age", "value" : 10 }
    ]
}

/* 2 */
{  "name" : "bob",
   "attibutes" : [   {  "key" : "marks", "value" : 20 } ]
}

/* 3 */
{ "name" : "charlie",
  "attibutes" : [  { "key" : "age", "value" : 20 } ]
}

/* 4 */
{ "name" : "dan",
  "attibutes" : []
}

/* 5 */
{ "name" : "el",
  "attibutes" : [ 
        { "key" : "marks", "value" : 5}, 
        { "key" : "age", "value" : 5}
    ]
}

我的用例是我需要标记上的文档过滤年龄上的排序。并非我的所有文档都具有必要的数据。 我希望输出中没有没有标记的文档,但是即使文档没有使用期限,也希望该文档出现在输出中。

查询1:仅过滤标记,按预期方式工作,返回两个文档

db.getCollection('students').aggregate([
{
  $match: {
    attributes: { 
      $elemMatch: {
        value: {$gte:10},
        key:"marks"
      }
    }
    }
  }
]) 

返回与Alice和Bob对应的文档。 预期

现在添加排序,这是我通过展开来完成的,查询看起来像

db.getCollection('students').aggregate([  
  {  
    $match:{  
      attributes:{  
        $elemMatch:{  
          value:{  
            $gte:10
          },
          key:"marks"
        }
      }
    }
  },
  {  $addFields:{ attributes_unwind:"$attributes" } },
  {  $unwind:"$attributes_unwind" }, //UNWIND OPERATION
  {  $match:{  "attributes_unwind.key":"age" } },
  {  $sort:{  "attributes_unwind.value":1 } },
  {  $project:{    "attributes_unwind":false } }
])

由于展开+匹配+排序,此查询删除了与bob对应的文档,该文档没有 age 条目。

我想通过在标记// UNWIND OPERATION的行之前添加age的键值(sort属性)来绕过此问题。仅当原始列表没有年龄密钥时,才应有条件地插入此内容。

到目前为止,我是

db.getCollection('students').aggregate([
{
    $match: {
attributes: { 
                    $elemMatch: {
                        value: {$gte:10},
                        key:"marks"
                        }
                    }
    }
},
{ $addFields: { attributes_unwind: "$attributes" } },
{ $addFields: 
    { attributes_unwind: 
        { $cond :
            [
            {
                attributes_unwind :{ $elemMatch:{key:"age"}}
            },
            "$attributes_unwind",
            { $concatArrays: [ "$attributes_unwind", [ {"key":"age","value":""}] ] } 
            ]
        }
    }
},
{ $unwind: "$attributes_unwind" },
{ $match: {"attributes_unwind.key": "age"}},
{ $sort: {"attributes_unwind.value": 1}},
{ $project: {"attributes_unwind": false}}
 ])

但是如果出现错误

Error: command failed: {
    "ok" : 0,
    "errmsg" : "Unrecognized expression '$elemMatch'",
    "code" : 168,
    "codeName" : "InvalidPipelineOperator"
} : aggregate failed 

1 个答案:

答案 0 :(得分:1)

我通过过滤器->尺寸-> gt-> cond解决了这个问题。在此处共享解决方案。我愿意提出更好的查询意见

5693
5701
5747
5747
5747
5812
5822
5822