如何使用相应文档的数组获取每个组的字段的最大值?

dap*_*mao 8 mongodb mongodb-query aggregation-framework

我有一个像

{
    "_id" : ObjectId("5738cb363bb56eb8f76c2ba8"),
    "records" : [
        {
            "Name" : "Joe",
            "Salary" : 70000,
            "Department" : "IT"
        }
    ]
},
{
    "_id" : ObjectId("5738cb363bb56eb8f76c2ba9"),
    "records" : [
        {
            "Name" : "Henry",
            "Salary" : 80000,
            "Department" : "Sales"
        },
        {
            "Name" : "Jake",
            "Salary" : 40000,
            "Department" : "Sales"
        }
    ]
},
{
    "_id" : ObjectId("5738cb363bb56eb8f76c2baa"),
    "records" : [
        {
            "Name" : "Sam",
            "Salary" : 90000,
            "Department" : "IT"
        },
        {
            "Name" : "Tom",
            "Salary" : 50000,
            "Department" : "Sales"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我想得到每个部门薪水最高的结果

{"Name": "Sam", "Salary": 90000, "Department": "IT"}
{"Name": "Henry", "Salary": 80000, "Department": "Sales"}
Run Code Online (Sandbox Code Playgroud)

我可以获得最高薪水.但我无法获得相应的员工姓名.

db.HR.aggregate([

    { "$unwind": "$records" },
    { "$group": 
        {
            "_id": "$records.Department",
            "max_salary": { "$max": "$records.Salary" }
        }
    }   
])
Run Code Online (Sandbox Code Playgroud)

有人能帮帮我吗?

sty*_*ane 7

您需要$sort在文档之后$unwind使用该文档中的$first操作符$group.您也可以使用$last运算符,在这种情况下,您需要按升序对文档进行排序

db.HR.aggregate([
    { '$unwind': '$records' }, 
    { '$sort': { 'records.Salary': -1 } }, 
    { '$group': { 
        '_id': '$records.Department', 
        'Name': { '$first': '$records.Name' } , 
        'Salary': { '$first': '$records.Salary' }
    }}
])
Run Code Online (Sandbox Code Playgroud)

产生:

{ "_id" : "Sales", "Name" : "Henry", "Salary" : 80000 }
{ "_id" : "IT", "Name" : "Sam", "Salary" : 90000 }
Run Code Online (Sandbox Code Playgroud)

要返回每个部门的最高工资和员工列表,您需要使用$max组阶段中的每个组返回最大"工资",然后使用$push累加器操作员为所有员工返回"名称"和"薪水"列表每组.从那里你需要使用阶段中的$map运算符$project来返回名称列表以及最高薪水.当然,$cond这里用于将每个员工薪水与最大值进行比较.在$setDifference做他的工作,这是过滤掉所有false,是罚款,只要被过滤的数据是"独一无二的".在这种情况下,它"应该"没问题,但如果任何两个结果包含相同的"名称",那么它会通过将两者视为一个来扭曲结果.

db.HR.aggregate([
    { '$unwind': '$records' },
    { '$group': {
        '_id': '$records.Department', 
        'maxSalary': { '$max': '$records.Salary' }, 
        'persons': { 
            '$push': {
                'Name': '$records.Name', 
                'Salary': '$records.Salary' 
            }
        }
    }}, 
    { '$project': { 
        'maxSalary': 1, 
        'persons': { 
            '$setDifference': [
                { '$map': {
                    'input': '$persons', 
                    'as': 'person', 
                    'in': {
                        '$cond': [
                            { '$eq': [ '$$person.Salary', '$maxSalary' ] }, 
                            '$$person.Name', 
                            false
                        ]
                    }
                }}, 
                [false]
            ]
        }
    }}
])
Run Code Online (Sandbox Code Playgroud)

产量:

{ "_id" : "Sales", "maxSalary" : 80000, "persons" : [ "Henry" ] }
{ "_id" : "IT", "maxSalary" : 90000, "persons" : [ "Sam" ] }
Run Code Online (Sandbox Code Playgroud)