MongoDB 按数组元素对文档排序
MongoDB sort documents by array elements
我的文档结构如下:
{
map: 'A',
points: [
{
type: 'type1',
distanceToSpawn: 110
},
{
type: 'type4',
distanceToSpawn: 40
},
{
type: 'type6',
distanceToSpawn: 30
}
]
},
{
map: 'B',
points: [
{
type: 'type1',
distanceToSpawn: 100
},
{
type: 'type2',
distanceToSpawn: 60
},
{
type: 'type3',
distanceToSpawn: 25
}
]
},
{
map: 'C',
points: [
{
type: 'type2',
distanceToSpawn: 90
},
{
type: 'type3',
distanceToSpawn: 1
},
{
type: 'type6',
distanceToSpawn: 76
}
]
}
我想获取点类型为 type1
的所有地图,按 distanceToSpawn
升序排列。
预期结果:
{
map: 'B',
points: [
{
type: 'type1',
distanceToSpawn: 100
}
]
},
{
map: 'A',
points: [
{
type: 'type1',
distanceToSpawn: 110
}
]
}
我试过类似的东西:
db.maps.find({'points.type': {$eq : 'type1'}}, {map: 1, 'points.$':1}).sort({'points.distanceToSpawn': 1}).limit(10)
但是这个东西不是按升序排列地图的。
谢谢。
你不能用数组做到这一点,这里的主要问题是因为你希望 "sort" 发生在匹配的元素上。如果你想像这样对结果进行排序,那么你需要使用 .aggregate()
来代替。作为:
对于现代 MongoDB 版本:
db.maps.aggregate([
{ "$match": { "points.type": "type1" }},
{ "$addFields": {
"order": {
"$filter": {
"input": "$points",
"as": "p",
"cond": { "$eq": [ "$$p.type", "type1" ] }
}
}
}},
{ "$sort": { "order": 1 } }
])
对于 MongoDB 2.6 到 3.0
db.maps.aggregate([
{ $match: { 'points.type': 'type1' } },
{
$project: {
points: {
$setDifference: [
{
$map: {
input: '$points',
as: 'p',
in: {
$cond: [
{ $eq: ['$$p.type', 'type1'] },
'$$p',
false,
]
}
}
},
[false]
]
}
}
},
{ $sort: { 'points.distanceToSpawn': 1 } },
]);
或在 MongoDB 2.6 之前的版本中效率较低:
db.maps.aggregate([
{ "$match": { "points.type": "type1" }},
{ "$unwind": "$points" },
{ "$match": { "points.type": "type1" }},
{ "$group": {
"_id": "$_id",
"points": { "$push": "$points" }
}},
{ "$sort": { "points.ditanceToSpawn": 1 } }
])
这是匹配正确元素并在 "sort" 操作中考虑它们的唯一方法。默认游标排序只会考虑数组元素中与您选择的字段不匹配的字段值 "type"。
我的文档结构如下:
{
map: 'A',
points: [
{
type: 'type1',
distanceToSpawn: 110
},
{
type: 'type4',
distanceToSpawn: 40
},
{
type: 'type6',
distanceToSpawn: 30
}
]
},
{
map: 'B',
points: [
{
type: 'type1',
distanceToSpawn: 100
},
{
type: 'type2',
distanceToSpawn: 60
},
{
type: 'type3',
distanceToSpawn: 25
}
]
},
{
map: 'C',
points: [
{
type: 'type2',
distanceToSpawn: 90
},
{
type: 'type3',
distanceToSpawn: 1
},
{
type: 'type6',
distanceToSpawn: 76
}
]
}
我想获取点类型为 type1
的所有地图,按 distanceToSpawn
升序排列。
预期结果:
{
map: 'B',
points: [
{
type: 'type1',
distanceToSpawn: 100
}
]
},
{
map: 'A',
points: [
{
type: 'type1',
distanceToSpawn: 110
}
]
}
我试过类似的东西:
db.maps.find({'points.type': {$eq : 'type1'}}, {map: 1, 'points.$':1}).sort({'points.distanceToSpawn': 1}).limit(10)
但是这个东西不是按升序排列地图的。
谢谢。
你不能用数组做到这一点,这里的主要问题是因为你希望 "sort" 发生在匹配的元素上。如果你想像这样对结果进行排序,那么你需要使用 .aggregate()
来代替。作为:
对于现代 MongoDB 版本:
db.maps.aggregate([
{ "$match": { "points.type": "type1" }},
{ "$addFields": {
"order": {
"$filter": {
"input": "$points",
"as": "p",
"cond": { "$eq": [ "$$p.type", "type1" ] }
}
}
}},
{ "$sort": { "order": 1 } }
])
对于 MongoDB 2.6 到 3.0
db.maps.aggregate([
{ $match: { 'points.type': 'type1' } },
{
$project: {
points: {
$setDifference: [
{
$map: {
input: '$points',
as: 'p',
in: {
$cond: [
{ $eq: ['$$p.type', 'type1'] },
'$$p',
false,
]
}
}
},
[false]
]
}
}
},
{ $sort: { 'points.distanceToSpawn': 1 } },
]);
或在 MongoDB 2.6 之前的版本中效率较低:
db.maps.aggregate([
{ "$match": { "points.type": "type1" }},
{ "$unwind": "$points" },
{ "$match": { "points.type": "type1" }},
{ "$group": {
"_id": "$_id",
"points": { "$push": "$points" }
}},
{ "$sort": { "points.ditanceToSpawn": 1 } }
])
这是匹配正确元素并在 "sort" 操作中考虑它们的唯一方法。默认游标排序只会考虑数组元素中与您选择的字段不匹配的字段值 "type"。