Монго БД найти все записи с наибольшим значением в зависимости от ключевого поля - PullRequest
0 голосов
/ 15 февраля 2019

Я хотел бы получить для каждого пользователя в моей коллекции комментарий записи с самым высоким значением.

//myCol
[
    {'user' : 1, 'value':20, "comment": "cloudy", "date":"2018-12-01"},
    {'user' : 2, 'value':5, "comment": "sun","date":"2018-12-01"},
    {'user' : 3, 'value':13, "comment": "rain","date":"2018-13-01"},
    {'user' : 4, 'value':13, "comment": "cloudy","date":"2018-13-01"},
    {'user' : 2, 'value':20, "comment": "rain","date":"2018-01-20"},
    {'user' : 1, 'value':2, "comment": "cloudy","date":"2018-02-02"},
]

Даст следующий результат:

//Result 
[
    {'user' : 1, 'value':20, "comment": "cloudy", "date":"2018-12-01"},
    {'user' : 2, 'value':20, "comment": "rain","date":"2018-01-20"},
    {'user' : 3, 'value':13, "comment": "rain","date":"2018-13-01"},
    {'user' : 4, 'value':13, "comment": "cloudy","date":"2018-13-01"},
]

С MySQLЯ бы использовал некоторую логику соединения

SELECT user FROM myTable as t0
LEFT JOIN (SELECT user, max(value) as maxVal from myTable ) t1 on t0.user = t1.user and t0.value = t1.maxVal
WHERE maxVal IS NOT NULL

С Mongo, однако, эта логика, кажется, не существует.

Я попытался разделить код на две части, получив сначала максимальные значения для каждого пользователя:

max_list = myCol.aggregate(
   [
     {
       "$group":
         {
           "_id": "$user",
           "maxValue": { "$max": "$value" }
         }
     },
     { 
            "$project" : {
                "user" : "$_id", 
                "maxValue":"$maxValue",
                "_id":0
            }
        }
   ]
)
 ==> [{'user':1, 'maxValue':20}...]

С этим я почесал голову за хороший способ использования функции find и особенно хорошее использование $in, чтобы получить только те результаты, которые соответствуют обоим значениям, присутствующим в my_list

Ответы [ 3 ]

0 голосов
/ 15 февраля 2019

Да, но подход немного другой:

db.myCol.aggregate([
    {$sort: {value:-1}},
    {$group:{
        _id: "$user",
        doc: {$first: "$$ROOT"}
    }},
    {$replaceRoot: {newRoot: "$doc"} }
])
0 голосов
/ 15 февраля 2019

Вы можете даже сделать только с двумя этапами

db.collection.aggregate([
  { "$group": {
    "_id": "$user",
    "doc": {
      "$max": {
        "value": "$value",
        "user": "$user",
        "comment": "$comment",
        "date": "$date"
      }
    }
  }},
  { "$replaceRoot": { "newRoot": "$doc" }}
])

$max всегда принимает максимальное значение первого выражения, которое передается внутри объекта,Вот оно value.

0 голосов
/ 15 февраля 2019

Вы можете $ отсортировать ваши документы по value до подачи заявления $ group с $ first

db.myCol.aggregate([
    { 
        $sort: { value: -1 }
    },
    {
        $group: {
            _id: "$user",
            value: { $first: "$value" },
            comment: { $first: "$comment" },
            date: { $first: "$date" }
        }
    },
    {
        $sort: { _id: 1 }
    },
    {
        $project: {
            user: "$_id",
            _id: 0,
            value: 1,
            comment: 1,
            date: 1
        }
    }
])
...