2015-11-30 15 views
8

मैं प्रत्येक विभागसंबंधित समूह की सरणी के साथ प्रत्येक समूह के लिए फ़ील्ड का अधिकतम मूल्य कैसे प्राप्त करें?

{"Name": "Sam", "Salary": 90000, "Department": "IT"} 
{"Name": "Henry", "Salary": 80000, "Department": "Sales"} 

मैं सबसे अधिक वेतन मिल सकता है द्वारा की तरह

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

मैं सबसे अधिक वेतन के साथ परिणाम करना चाहते हैं एक संग्रह है। लेकिन मुझे संबंधित कर्मचारी नाम नहीं मिल सका।

db.HR.aggregate([ 

    { "$unwind": "$records" }, 
    { "$group": 
     { 
      "_id": "$records.Department", 
      "max_salary": { "$max": "$records.Salary" } 
     } 
    } 
]) 

किसी ने मुझसे मदद कर सकता है?

+0

बड़ा सवाल है, तो आप को जोड़ सकते हैं कि तुम क्या करने की कोशिश की और एक त्रुटि मिल गया है? – inspired

+0

मैं एसक्यूएल में स्वयं से जुड़ने के साथ इसे हल कर सकता हूं। लेकिन मुझे मोंगो के साथ कोई रास्ता नहीं मिल रहा है – dapangmao

उत्तर

7

आपको $sort$unwind के बाद अपने दस्तावेज़ की आवश्यकता है और $group चरण में $first ऑपरेटर का उपयोग करें। तुम भी $last ऑपरेटर का उपयोग कर सकते हैं जिस स्थिति में आप आरोही क्रम में अपने दस्तावेज़ों को सॉर्ट करने की आवश्यकता होगी

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

जो पैदा करता है:

{ "_id" : "Sales", "Name" : "Henry", "Salary" : 80000 } 
{ "_id" : "IT", "Name" : "Sam", "Salary" : 90000 } 

अधिकतम वेतन और कर्मचारियों सूची वापस जाने के लिए प्रत्येक विभाग के लिए आपको प्रत्येक समूह के लिए अधिकतम "वेतन" वापस करने के लिए अपने समूह चरण में $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] 
      ] 
     } 
    }} 
]) 

जो पैदावार:

{ "_id" : "Sales", "maxSalary" : 80000, "persons" : [ "Henry" ] } 
{ "_id" : "IT", "maxSalary" : 90000, "persons" : [ "Sam" ] } 
3

इसके नहीं सबसे सहज बात है, लेकिन $max के बजाय आप $sort और $first का उपयोग कर किया जाना चाहिए:

{ "$unwind": "$records" }, 
{ "$sort": { "$records.Salary": -1}, 
{ "$group" : 
    { 
     "_id": "$records.Department", 
     "max_salary": { "$first": "$records.Salary" }, 
     "name": {$first: "$records.Name"} 
    } 
} 
वैकल्पिक रूप से

, मुझे लगता है कि यह संभव है $$ROOT ऑपरेटर का उपयोग करके (उचित चेतावनी: मैंने वास्तव में यह कोशिश नहीं की है) -

{ "$unwind": "$records" }, 
{ "$group": 
     { 
      "_id": "$records.Department", 
      "max_salary": { "$max": "$records.Salary" } 
      "name" : "$$ROOT.records.Name" 
     } 
    } 
} 
1

एक अन्य संभावित समाधान:

db.HR.aggregate([ 
    {"$unwind": "$records"}, 
    {"$group":{ 
     "_id": "$records.Department", 
     "arr": {"$push": {"Name":"$records.Name", "Salary":"$records.Salary"}}, 
     "maxSalary": {"$max":"$records.Salary"} 
    }}, 
    {"$unwind": "$arr"}, 
    {"$project": { 
     "_id":1, 
     "arr":1, 
     "isMax":{"$eq":["$arr.Salary", "$maxSalary"]} 
    }}, 
    {"$match":{ 
     "isMax":true 
    }} 
]) 

यह समाधान $project चरण में दो क्षेत्रों की तुलना करने के $eq ऑपरेटर का लाभ लेता है।

टेस्ट मामला:

db.HR.insert({"records": [{"Name": "Joe", "Salary": 70000, "Department": "IT"}]}) 
db.HR.insert({"records": [{"Name": "Henry", "Salary": 80000, "Department": "Sales"}, {"Name": "Jake", "Salary": 40000, "Department": "Sales"}, {"Name": "Santa", "Salary": 90000, "Department": "IT"}]}) 
db.HR.insert({"records": [{"Name": "Sam", "Salary": 90000, "Department": "IT"}, {"Name": "Tom", "Salary": 50000, "Department": "Sales"}]}) 

परिणाम:

{ "_id" : "Sales", "arr" : { "Name" : "Henry", "Salary" : 80000 }, "isMax" : true } 
{ "_id" : "IT", "arr" : { "Name" : "Santa", "Salary" : 90000 }, "isMax" : true } 
{ "_id" : "IT", "arr" : { "Name" : "Sam", "Salary" : 90000 }, "isMax" : true } 
संबंधित मुद्दे