MongoDB sorts documents by array elements

I have a document structure like:

{ 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 } ] } 

I want all the cards to have a type1 point type, sorted by distanceToSpawn in ascending order.

Expected Result:

 { map: 'B', points: [ { type: 'type1', distanceToSpawn: 100 } ] }, { map: 'A', points: [ { type: 'type1', distanceToSpawn: 110 } ] } 

I tried something like:

 db.maps.find({'points.type': {$eq : 'type1'}}, {map: 1, 'points.$':1}).sort({'points.distanceToSpawn': 1}).limit(10) 

But this thing does not sort the cards in ascending order.

Thanks.

+6
source share
1 answer

You cannot do this with arrays, and the main problem here is that you want the "sorting" to be performed on the matched element. If you want to sort results like this, then you need to use .aggregate() . Or like:

For modern versions of MongoDB:

 db.maps.aggregate([ { "$match": { "points.type": "type1" }}, { "$addFields": { "order": { "$filter": { "input": "$points", "as": "p", "cond": { "$eq": [ "$$p.type", "type1" ] } } } }}, { "$sort": { "order": 1 } } ]) 

For MongoDB 2.6 to 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 } } ]) 

Or less effective in versions prior to 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 } } ]) 

This is the only way to match the correct elements and consider them in a sort operation. Sorting the cursor by default will look differently at field values ​​in array elements that do not match the type you selected.

+7
source

Source: https://habr.com/ru/post/983403/


All Articles