如何解决mongodb:使用字段名称的动态参数对嵌套数组进行排序
假设在聚合管道中,其中一个步骤将产生以下结果:
{
customer: "WN",sort_category: "category_a",locations: [
{
city: "Elkana",category_a: 11904.0,category_b: 74.0,category_c: 657.0,},{
city: "Haifa",category_a: 20.0,category_b: 841.0,category_c: 0,{
city" : "Jerusalem",category_a: 451.0,category_b: 45.0,category_c: 712.0,}
]
}
{
...
}
下一步是对集合中每个文档的嵌套对象列表进行排序。
嵌套对象的列表应按包含字段名称的动态参数排序。
例如-locations
的列表应按category_a
的值排序。
category_a
是sort_category
字段中给出的参数。
解决方法
这是不使用$function
的解决方案:
db.tests.aggregate([
{$unwind:"$locations"},{$project: {
_id: 1,customer: 1,sort_category: 1,locations: 1,locationsKV:{$objectToArray:"$locations"}
}
},{$unwind:"$locationsKV"},{$project:{
_id: 1,locationsKV: 1,category: {
$cond:[{$eq: ["$sort_category","$locationsKV.k"]},"$locationsKV.v",0]},agg: {
$cond: [{$eq: ["$sort_category",true,false]
}
}
},{$match: {agg: true}},{$sort: {category: 1}},{$group: {
_id: "$_id",customer: {$first: "$customer"},sort_category: {$first: "$sort_category"},locations: {$push: "$locations"}
}
},{$project:{ _id: 0}}
])
,
您可以尝试自定义方式,
-
$addFields
将使用category
和sort_category
在locations
数组中的每个对象内添加一个名为键$map
的复制字段$reduce
,{1} li> -
$unwind
解构locations
数组
我们在 -
category
和locations
字段 -
$project
删除category
字段 -
$group
by _id并重建locations
数组 -
$project
删除_id
字段
$sort
数组中添加的db.collection.aggregate([
{
$addFields: {
locations: {
$map: {
input: "$locations",as: "l",in: {
$mergeObjects: [
"$$l",{
category: {
$reduce: {
input: { $objectToArray: "$$l" },initialValue: null,in: {
$cond: [{ $eq: ["$$this.k","$sort_category"] },"$$this.v","$$value"]
}
}
}
}
]
}
}
}
}
},{ $unwind: "$locations" },{ $sort: { "locations.category": 1 } },{ $project: { "locations.category": 0 } },{
$group: {
_id: "$_id",customer: { $first: "$customer" },sort_category: { $first: "$sort_category" },locations: { $push: "$locations" }
}
},{ $project: { _id: 0 } }
])
如果您打算将 MongoDB升级到v4.4 ,或者这也将对其他人有所帮助,则$function是自定义操作和用户定义操作的选项。
共有3个属性:
-
body
函数定义。您可以将函数定义指定为BSON类型的Code或String,使用function(){
定义我们自己的函数,我们传递了locations
数组和sort_category
这是动态字段,函数逻辑是排序的按降序 -
args
参数传递给函数主体 -
lang
身体使用的语言。您必须指定lang:“ js”
db.collection.aggregate([
{
$addFields: {
locations: {
$function: {
body: function(locations,sort_category){
return locations.sort(function(a,b){
// DESCENDING ORDER
return b[sort_category] - a[sort_category]
// ASCENDING ORDER
// return a[sort_category] - b[sort_category]
})
},args: ["$locations","$sort_category"],lang: "js"
}
}
}
}
])
有关限制和注意事项的更多准则Refer。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。