Как получить пять самых быстрых наземных скоростей с помощью mongodb

#mongodb #sorting #mongodb-query #aggregation-framework #mongodb-aggregation

#mongodb — монгодб #сортировка #mongodb-запрос #агрегация-фреймворк #mongodb-агрегация #mongodb

Вопрос:

Итак, у меня есть эти данные, импортированные из Excel, и я хочу иметь возможность находить пять самых быстрых скоростей. Я попытался использовать агрегатную функцию, но было возвращено значение 0.

 db.planes.aggregate({
    $group : {
        _id : "$msg_dummy",
        fastest : {$max : "$ground_speed"}
    }
})


{ "_id" : "MSG", "fastest" : "" }
  

и распечатана только одна. Мне нужна первая пятерка. Вот некоторые из этих данных

 { "_id" : ObjectId("58076dffa85331269df16994"), "msg_dummy" : "MSG", "msg_type" : 4, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214224, "latitude" : "", "longitude" : 306, "altitude" : 133, "ground_speed" : -512, "heading" : "", "dummy1" : "" }
{ "_id" : ObjectId("58076dffa85331269df16995"), "msg_dummy" : "MSG", "msg_type" : 4, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214223, "latitude" : "", "longitude" : 307, "altitude" : 133, "ground_speed" : -512, "heading" : "", "dummy1" : "" }
{ "_id" : ObjectId("58076dffa85331269df16996"), "msg_dummy" : "MSG", "msg_type" : 1, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214223, "latitude" : "", "longitude" : "", "altitude" : "", "ground_speed" : "" }
{ "_id" : ObjectId("58076dffa85331269df16997"), "msg_dummy" : "MSG", "msg_type" : 4, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214223, "latitude" : "", "longitude" : 307, "altitude" : 133, "ground_speed" : -512, "heading" : "", "dummy1" : "" }
{ "_id" : ObjectId("58076dffa85331269df16998"), "msg_dummy" : "MSG", "msg_type" : 1, "flight_id" : "AAL1538", "aircraft_id" : "ABFEFD", "date" : 20131213, "time" : 214224, "latitude" : "", "longitude" : "", "altitude" : "", "ground_speed" : "" }
{ "_id" : ObjectId("58076dffa85331269df16999"), "msg_dummy" : "MSG", "msg_type" : 4, "flight_id" : "AAL1538", "aircraft_id" : "ABFEFD", "date" : 20131213, "time" : 214224, "latitude" : "", "longitude" : 298, "altitude" : 123, "ground_speed" : 64, "heading" : "", "dummy1" : "" }
{ "_id" : ObjectId("58076dffa85331269df1699a"), "msg_dummy" : "MSG", "msg_type" : 4, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214224, "latitude" : "", "longitude" : 306, "altitude" : 133, "ground_speed" : -512, "heading" : "", "dummy1" : "" }
{ "_id" : ObjectId("58076dffa85331269df1699b"), "msg_dummy" : "MSG", "msg_type" : 1, "flight_id" : "NKS355", "aircraft_id" : "A67CA6", "date" : 20131213, "time" : 214225, "latitude" : "", "longitude" : "", "altitude" : "", "ground_speed" : "" }
{ "_id" : ObjectId("58076dffa85331269df1699c"), "msg_dummy" : "MSG", "msg_type" : 3, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214225, "latitude" : 28.64559, "longitude" : -81.57871, "altitude" : 10100, "ground_speed" : 306, "heading" : 133, "dummy1" : -512, "dummy2" : "", "field13" : "" }
{ "_id" : ObjectId("58076dffa85331269df1699d"), "msg_dummy" : "MSG", "msg_type" : 3, "flight_id" : 680, "aircraft_id" : "A1C8EB", "date" : 20131213, "time" : 214225, "latitude" : 28.64517, "longitude" : -81.57823, "altitude" : 10100, "ground_speed" : 306, "heading" : 133, "dummy1" : -512, "dummy2" : "", "field13" : "" }
{ "_id" : ObjectId("58076dffa85331269df1699e"), "msg_dummy" : "MSG", "msg_type" : 4, "flight_id" : "AAL1538", "aircraft_id" : "ABFEFD", "date" : 20131213, "time" : 214225, "latitude" : "", "longitude" : 298, "altitude" : 123, "ground_speed" : 64, "heading" : "", "dummy1" : "" }
  

Ответ №1:

Поскольку ground_speed поле содержит смесь числовых и строковых значений (пустая строка), $max оператор возвращает максимальное значение, поскольку он сравнивает как значение, так и тип, используя указанный порядок сравнения BSON для значений разных типов.

Вам нужно отфильтровать документы и сравнить только те, у которых есть числовые значения для ground_speed :

 db.planes.aggregate([
    { "$match": { 
        "ground_speed": { "$exists": true, "$type": 1 }  
    } },
    {
        "$group" : {
            "_id" : "$msg_dummy",
            "fastest" : { "$max" : "$ground_speed"}
        }
    }
])
  

Чтобы ответить на ваш вопрос, для получения 5 лучших скоростей требуется упорядочить документы по ground_speed полю с помощью $sort конвейера, создать массив со ground_speed значениями в $group конвейере с помощью оператора накопителя $push , а затем вернуть 5 лучших из массива с помощью $project конвейера и $slice оператора.

Следующий пример показывает это:

 db.planes.aggregate([
    { "$match": { 
        "ground_speed": { "$exists": true, "$type": 1 }  
    } },
    { "$sort": { "ground_speed": -1 } },
    {
        "$group" : {
            "_id" : "$msg_dummy",
            "ground_speeds" : { "$push" : "$ground_speed" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "msg_dummy": "$_id",
            "top_five_fastest": { "$slice": ["$ground_speeds", 5] },
            "ground_speeds": 1
        }
    }
])
  

Для версий MongoDB, которые не поддерживают $slice оператор, в качестве альтернативы вы можете получить 5 лучших, ограничив количество документов, поступающих в $group конвейер с помощью $limit оператора, и это должно быть помещено после $sort конвейера (для упорядоченных документов):

 db.planes.aggregate([
    { "$match": { 
        "ground_speed": { "$exists": true, "$type": 1 }  
    } },
    { "$sort": { "ground_speed": -1 } },
    { "$limit": 5 },
    {
        "$group" : {
            "_id" : "$msg_dummy",
            "top_five_fastest" : { "$push" : "$ground_speed" }
        }
    }   
])
  

Ответ №2:

Вы можете сделать это без использования агрегированного запроса.

Попробуйте следующее:

  db.planes.find({},{_id:1,ground_speed:1}).sort({ground_speed:-1}).limit(5)
  

Комментарии:

1. Большое спасибо, это очень помогло

2. Всегда пожалуйста. Если вы довольны ответом, можете ли вы принять его, пожалуйста?