Mongodb geoNear 和组聚合
Mongodb geoNear and group aggregation
我一直在网上搜索与此相关的内容,但找不到。
我有这个聚合
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}},
{ $group:
{ _id: "$_id",
name: { '$first': '$name' },
distance: { $first: "$distance" }
}
},
{ $project : {
name: 1,
distance: 1,
}}
],
function(error, places) {
if (error) return callback(error, null);
callback(null, places)
}
);
有效,但 geoNear 排序丢失了!
但这给了我正确排序的文档:
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}}
],
function(error, places) {
if (error) return callback(error, null);
callback(null, places)
}
);
有什么想法吗?
为了让您了解我在这里尝试做的事情是我使用
的完整查询
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}},
{"$unwind": "$participants" } ,
{ $group:
{ _id: "$_id",
name: { '$first': '$name' },
distance: { $first: "$distance" },
person: { $sum: 1 },
sumof:{ $sum: "$participants.age"}
}
},
{ $project : {
name: name,
distance: 1,
person: 1,
meanAge:{ $divide: [ "$sumof", "$person" ]}
}}
],
function(error, places) {
if (error) return callback(error, null);
callback(null, places)
}
);
简而言之,当您使用 $group
等运算符时,无法保证返回结果的顺序。文档将按照 "input" 到组管道的顺序进行处理,以纪念诸如 $first
之类的事情,但输出不一定按照它进入的顺序出现。
直接来自文档:
$group does not order its output documents.
事实上,您可能会发现顺序是按分组键排序的,但在大多数情况下是相反的。
如果您想要特定的输出顺序,请使用 $sort
,对于最终的 "output",这应该是您的最后一个流水线阶段,因此不会有任何其他改变该顺序。
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}},
{ "$unwind": "$participants" } ,
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"distance": { "$first": "$distance" },
"person": { "$sum": 1 },
"sumof":{ "$sum": "$participants.age" }
}},
{ "$project" : {
"name": 1,
"distance": 1,
"person": 1,
"meanAge": { "$divide": [ "$sumof", "$person" ]}
}},
{ "$sort": { "distance": 1 } }
],
callback
);
我一直在网上搜索与此相关的内容,但找不到。
我有这个聚合
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}},
{ $group:
{ _id: "$_id",
name: { '$first': '$name' },
distance: { $first: "$distance" }
}
},
{ $project : {
name: 1,
distance: 1,
}}
],
function(error, places) {
if (error) return callback(error, null);
callback(null, places)
}
);
有效,但 geoNear 排序丢失了!
但这给了我正确排序的文档:
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}}
],
function(error, places) {
if (error) return callback(error, null);
callback(null, places)
}
);
有什么想法吗?
为了让您了解我在这里尝试做的事情是我使用
的完整查询 Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}},
{"$unwind": "$participants" } ,
{ $group:
{ _id: "$_id",
name: { '$first': '$name' },
distance: { $first: "$distance" },
person: { $sum: 1 },
sumof:{ $sum: "$participants.age"}
}
},
{ $project : {
name: name,
distance: 1,
person: 1,
meanAge:{ $divide: [ "$sumof", "$person" ]}
}}
],
function(error, places) {
if (error) return callback(error, null);
callback(null, places)
}
);
简而言之,当您使用 $group
等运算符时,无法保证返回结果的顺序。文档将按照 "input" 到组管道的顺序进行处理,以纪念诸如 $first
之类的事情,但输出不一定按照它进入的顺序出现。
直接来自文档:
$group does not order its output documents.
事实上,您可能会发现顺序是按分组键排序的,但在大多数情况下是相反的。
如果您想要特定的输出顺序,请使用 $sort
,对于最终的 "output",这应该是您的最后一个流水线阶段,因此不会有任何其他改变该顺序。
Place.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"spherical": true,
"distanceField": "distance"
}},
{ "$unwind": "$participants" } ,
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"distance": { "$first": "$distance" },
"person": { "$sum": 1 },
"sumof":{ "$sum": "$participants.age" }
}},
{ "$project" : {
"name": 1,
"distance": 1,
"person": 1,
"meanAge": { "$divide": [ "$sumof", "$person" ]}
}},
{ "$sort": { "distance": 1 } }
],
callback
);