鉴于此类文件:
{
"_id" : "16",
"name" : "SB15",
"category_id" : 3,
"level" : 2,
"sizes" : [
{
"v" : 34.78
},
{
"v" : 32.15
},
{
"v" : 35.86
},
{
"v" : 39.4
},
{
"v" : 24.01
}
]
}
我需要为每个“category_id”值找到“size.v”具有小于给定数字的值的文档,并且该级别等于给定数字,并且对于每个category_id将文档限制为4
如果我找一个小于35的“size.v”
,结果应该是这样的{
"_id" : 3, /* the category_id */
"models" : [
{
"name": "SB15",
"level": 2,
"size": {
"v" : 34.78, /* the higher value in sizes array less than 35 */
"h" : 6.4,
"w" : 0.20,
"t" : 0.03
}
}
...,
...,
...,
]
}
答案 0 :(得分:1)
一般的想法是找出与目标值的差异,然后对结果进行排序:
对于MongoDB 2.6以上版本,$map
之前阵列上的$unwind
可能最好,因为处理开销较少:
db.collection.aggregate([
// Calculate the difference
{ "$project": {
"name": 1,
"category_id": 1,
"level": 1,
"sizes": {
"$map": {
"input": "$sizes",
"as": "el",
"in": {
"v": "$$el.v",
"diff": {
"$cond": [
{ "$gt": [ 35, "$$el.v" },
999999,
{ "$subtract": [ 35, "$$el.v" ] }
]
}
}
}
}
}},
// Unwind the array
{ "$unwind": "$sizes" },
// Sort to smallest difference
{ "$sort": { "_id": 1, "sizes.diff": 1 } },
// Get the $first after sort
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"category_id": { "$first": "$category_id" },
"level": { "$first": "$level" },
"size_v": { "$first": "$sizes.v" }
}},
// Since you cannot have nested paths in a $group
{ "$project": {
"name": 1,
"category_id": 1,
"level": 1,
"size": {
"v": "$size_v"
}
}},
// Group up by category
{ "$group": {
"_id": "$category_id",
"models": {
"$push": {
"name": "$name",
"level": "$level",
"size": "$size"
}
}
}}
])
在早期版本中$unwind
首先:
db.collection.aggregate([
{ "$unwind": "$sizes" },
{ "$project": {
"name": 1,
"category_id": 1,
"level": 1,
"sizes": {
"v": "$sizes.v",
"diff": {
"$cond": [
{ "$gt": [ 35, "$sizes.v" ] },
99999,
{ "$subtract": [ 35, "$sizes.v" ] }
]
}
}
}},
{ "$sort": { "_id": 1, "sizes.diff": 1 } },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"category_id": { "$first": "$category_id" },
"level": { "$first": "$level" },
"size_v": { "$first": "$sizes.v" }
}},
{ "$project": {
"name": 1,
"category_id": 1,
"level": 1,
"size": {
"v": "$size_v"
}
}},
{ "$group": {
"_id": "$category_id",
"models": {
"$push": {
"name": "$name",
"level": "$level",
"size": "$size"
}
}
}}
])
主要的计算是在$cond
内完成的,首先你要看看这个值是否大于目标,如果是,那么分配一个"差异"这是一个很大的价值。进一步远离可能的间隔越好。
它实际上小于目标,$subtract
来自目标的值。结果中的数字越小,越接近。
但基本情况是计算差异然后$sort
,因此最小值在顶部。然后,您可以再次$first
使用$group
选择该值。
另请注意,$group
不能将嵌套对象作为键,因此总计首先为"size_v"
,然后在稍后的"size.v"
阶段重命名为$project
以容纳变换。