2017-03-16 27 views
2

我有一個MongoDB的集合,它看起來像這樣:如何獲得mongoDB集合的排名位置?

[{ 
    "_id": 1, 
    "name": "John Doe", 
    "company": "Acme", 
    "email": "[email protected]", 
    "matches": [171844, 169729, 173168, 174310, 168752, 174972, 172959, 169546] 
}, { 
    "_id": 2, 
    "name": "Bruce Wayne", 
    "company": "Wayne Enterprises", 
    "email": "[email protected]", 
    "matches": [171844, 232333, 233312, 123456] 
}, { 
    "_id": 3, 
    "name": "Tony Stark", 
    "company": "Stark Industries", 
    "email": "[email protected]", 
    "matches": [173844, 155729, 133168, 199310, 132752, 139972] 
}, { 
    "_id": 4, 
    "name": "Clark Kent", 
    "company": "Daily Planet", 
    "email": "[email protected]", 
    "matches": [169729, 174310, 168752] 
}, { 
    "_id": 5, 
    "name": "Lois Lane", 
    "company": "Daily Planet", 
    "email": "[email protected]", 
    "matches": [172959, 169546] 
}] 

我需要得到用戶的過濾列表,但與顯示了基於「匹配」的數量用戶的「排行榜」上排名的關鍵記錄它有。 應該有一個「全球排名」職位和一個「公司排名」職位。

期望的結果應該是這樣的(對於一個例子公司=「每日星球」過濾):

[ { _id: 4, 
    name: 'Clark Kent', 
    company: 'Daily Planet', 
    email: '[email protected]', 
    points: 3, 
    globalRank: 4, 
    companyRank: 1 
    }, 
    { _id: 5, 
    name: 'Lois Lane', 
    company: 'Daily Planet', 
    email: '[email protected]', 
    points: 2, 
    globalRank: 4, 
    companyRank: 2 
    } ] 

注意,克拉克·肯特排名在全球排名第四,因爲他有3場比賽( John Doe,Bruce Wayne和Tony Stark比他擁有更多的比賽),並且在公司排名中排名第一,因爲他擁有比任何Daily Planet用戶更多的比賽。

但是,即使經過幾天的研究,我也找不到辦法做到這一點。 (我甚至不知道如何僅進行全球排名或公司排名)。

我使用如下下面總管道:

[{ 
    $match: { 
    company: "Daily Planet" 
    } 
}, { 
    $project: { 
    _id: 1, 
    name: "$name", 
    company: "$company", 
    email: "$email", 
    points: { 
     $size: "$matches" 
    } 
    } 
}, { 
    $sort: { 
    points: -1 
    } 
}] 

但這並不返回由點排列名次,只記錄。

關於如何解決這個問題或者如何以不同方式解決問題的想法?

+0

什麼的MongoDB的版本? – hyades

回答

1

基本思想是先按照points的順序對點進行排序,然後按照$push的順序對它們進行排序。這確保元素按排序順序插入。然後我們$unwind使用includeArrayIndex屬性來生成排序數組中對應於排名的元素的索引。

使用上述邏輯被如下(嘗試通過階段去階段更好地理解)管道: - 骨料 - [

{ 
     $project: { 
      _id: 1, 
      name: "$name", 
      company: "$company", 
      email: "$email", 
      points: { 
       $size: "$matches" 
      } 
     } 
    }, { 
     $sort: { 
      points: -1 
     } 
    }, 

    { 
     $group: { 
      _id: {}, 
      arr: { 
       $push: { 
        name: '$name', 
        company: '$company', 
        email: '$email', 
        points: '$points' 
       } 
      } 
     } 
    }, { 
     $unwind: { 
      path: '$arr', 
      includeArrayIndex: 'globalRank', 
     } 
    }, { 
     $sort: { 
      'arr.company': 1, 
      'arr.points': -1 
     } 
    }, { 
     $group: { 
      _id: '$arr.company', 
      arr: { 
       $push: { 
        name: '$arr.name', 
        company: '$arr.company', 
        email: '$arr.email', 
        points: '$arr.points', 
        globalRank: '$globalRank' 
       } 
      } 
     } 
    }, { 
     $unwind: { 
      path: '$arr', 
      includeArrayIndex: 'companyRank', 
     } 
    }, { 
     $project: { 
      _id: 0, 
      name: '$arr.name', 
      company: '$arr.company', 
      email: '$arr.email', 
      points: '$arr.points', 
      globalRank: '$arr.globalRank', 
      companyRank: '$companyRank' 
     } 
    } 

] 

查詢的輸出是

/* 1 */ 
{ 
    "companyRank" : NumberLong(0), 
    "name" : "Bruce Wayne", 
    "company" : "Wayne Enterprises", 
    "email" : "[email protected]", 
    "points" : 4, 
    "globalRank" : NumberLong(2) 
} 

/* 2 */ 
{ 
    "companyRank" : NumberLong(0), 
    "name" : "Tony Stark", 
    "company" : "Stark Industries", 
    "email" : "[email protected]", 
    "points" : 6, 
    "globalRank" : NumberLong(1) 
} 

/* 3 */ 
{ 
    "companyRank" : NumberLong(0), 
    "name" : "Clark Kent", 
    "company" : "Daily Planet", 
    "email" : "[email protected]", 
    "points" : 3, 
    "globalRank" : NumberLong(3) 
} 

/* 4 */ 
{ 
    "companyRank" : NumberLong(1), 
    "name" : "Lois Lane", 
    "company" : "Daily Planet", 
    "email" : "[email protected]", 
    "points" : 2, 
    "globalRank" : NumberLong(4) 
} 

/* 5 */ 
{ 
    "companyRank" : NumberLong(0), 
    "name" : "John Doe", 
    "company" : "Acme", 
    "email" : "[email protected]", 
    "points" : 8, 
    "globalRank" : NumberLong(0) 
} 

排名在0於此處。

+0

非常感謝! 「includeArrayIndex」是我一直在尋找的! –

0

您使用$匹配條件。所以,你試試這也..

db.rank.aggregate([{ 
    $match: { 
     "company": "Daily Planet" 
    } 
}, { 
    $project: { 
     _id: 1, 
     name: "$name", 
     company: "$company", 
     email: "$email", 
     points: { 
      $size: "$matches" 
     } 
    } 
}, { 
    $sort: { 
     points: -1 
    } 
}, { 
    $group: { 
     _id: {}, 
     list: { 
      $push: { 
       name: '$name', 
       company: '$company', 
       email: '$email', 
       points: '$points' 
      } 
     } 
    } 
}, { 
    $unwind: { 
     path: '$list', 
     includeArrayIndex: 'globalRank', 
    } 
}, { 
    $sort: { 
     'list.company': 1, 
     'list.points': -1 
    } 
}, { 
    $group: { 
     _id: '$list.company', 
     list: { 
      $push: { 
       name: '$list.name', 
       company: '$list.company', 
       email: '$list.email', 
       points: '$list.points', 
       globalRank: '$globalRank' 
      } 
     } 
    } 
}, { 
    $unwind: { 
     path: '$list', 
     includeArrayIndex: 'companyRank', 
    } 
}, { 
    $project: { 
     _id: 0, 
     name: '$list.name', 
     company: '$list.company', 
     email: '$list.email', 
     points: '$list.points', 
     globalRank: '$list.globalRank', 
     companyRank: '$companyRank' 
    } 
}]).pretty() 

輸出這樣的,

{ 
    "companyRank" : NumberLong(0), 
    "name" : "Clark Kent", 
    "company" : "Daily Planet", 
    "email" : "[email protected]", 
    "points" : 3, 
    "globalRank" : NumberLong(0) 
} 
{ 
    "companyRank" : NumberLong(1), 
    "name" : "Lois Lane", 
    "company" : "Daily Planet", 
    "email" : "[email protected]", 
    "points" : 2, 
    "globalRank" : NumberLong(1) 
} 
0

你期待這樣的結果? 。 result_array將保留最終結果。

var my_array = db.testCol.aggregate([{ $project: { _id:1, name:1, company:1, email:1, "points" : {$size: "$matches"}, "globalRank":{$literal: 0}, companyRank:{$literal: 0} } }, 
{$sort: {points : -1 } }, 
]).toArray() 

var result_array = []; 
var companyCount = {}; 
for (i = 0; i < my_array.length; i++) { 
    var company_name = my_array[i].company 
    if (companyCount[company_name] == null){ 
     companyCount[company_name] = 1; 
    } 
    else{ 
     companyCount[company_name] = companyCount[company_name] + 1 
    } 
    result_array.push({ "_id" : my_array[i]._id, "name": my_array[i].name, "company" : my_array[i].company, "email" : my_array[i].email, "points" : my_array[i].points, "globalRank":i+1 , "companyRank" : companyCount[company_name]}) 
} 

result_array 

,輸出是:

[ 
     { 
       "_id" : 1, 
       "name" : "John Doe", 
       "company" : "Acme", 
       "email" : "[email protected]", 
       "points" : 8, 
       "globalRank" : 1, 
       "companyRank" : 1 
     }, 
     { 
       "_id" : 3, 
       "name" : "Tony Stark", 
       "company" : "Stark Industries", 
       "email" : "[email protected]", 
       "points" : 6, 
       "globalRank" : 2, 
       "companyRank" : 1 
     }, 
     { 
       "_id" : 2, 
       "name" : "Bruce Wayne", 
       "company" : "Wayne Enterprises", 
       "email" : "[email protected]", 
       "points" : 4, 
       "globalRank" : 3, 
       "companyRank" : 1 
     }, 
     { 
       "_id" : 4, 
       "name" : "Clark Kent", 
       "company" : "Daily Planet", 
       "email" : "[email protected]", 
       "points" : 3, 
       "globalRank" : 4, 
       "companyRank" : 1 
     }, 
     { 
       "_id" : 5, 
       "name" : "Lois Lane", 
       "company" : "Daily Planet", 
       "email" : "[email protected]", 
       "points" : 2, 
       "globalRank" : 5, 
       "companyRank" : 2 
     } 
]