如何获得mongoDB集合的排名位置?

时间:2017-03-16 18:35:31

标签: mongodb

我有一个mongoDB集合,如下所示:

[{
    "_id": 1,
    "name": "John Doe",
    "company": "Acme",
    "email": "john.doe@acme.com",
    "matches": [171844, 169729, 173168, 174310, 168752, 174972, 172959, 169546]
}, {
    "_id": 2,
    "name": "Bruce Wayne",
    "company": "Wayne Enterprises",
    "email": "bruce@wayne.com",
    "matches": [171844, 232333, 233312, 123456]
}, {
    "_id": 3,
    "name": "Tony Stark",
    "company": "Stark Industries",
    "email": "tony@stark.com",
    "matches": [173844, 155729, 133168, 199310, 132752, 139972]
}, {
    "_id": 4,
    "name": "Clark Kent",
    "company": "Daily Planet",
    "email": "clark.kent@planet.com",
    "matches": [169729, 174310, 168752]
}, {
    "_id": 5,
    "name": "Lois Lane",
    "company": "Daily Planet",
    "email": "lois.lane@planet.com",
    "matches": [172959, 169546]
}]

我需要获得一个过滤的用户列表,但是需要一个显示用户"排名"基于"匹配数量的位置"它有的记录。 应该有一个全球排名"职位和公司排名"位置。

期望的结果应该是这个(例如过滤公司=' Daily Planet'):

[ { _id: 4,
    name: 'Clark Kent',
    company: 'Daily Planet',
    email: 'clark.kent@planet.com',
    points: 3, 
    globalRank: 4, 
    companyRank: 1
  },
  { _id: 5,
    name: 'Lois Lane',
    company: 'Daily Planet',
    email: 'lois.lane@planet.com',
    points: 2,
    globalRank: 4, 
    companyRank: 2
  } ]

请注意,自从他有3场比赛(John Doe,Bruce Wayne和Tony Stark比他更多的比赛)以来,Clark Kent在全球排名中排名第4,并且在公司排名中排名第一,因为他的比赛比任何比赛都多。每日星球用户。

然而,即使经过几天的研究,我也找不到办法。 (我甚至无法弄清楚如何进行全球排名或公司排名)。

我使用以下聚合管道,如下所示:

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

但是这并没有返回排名,只返回按点排序的记录。

有关如何解决此问题或如何以不同方式解决问题的任何想法?

3 个答案:

答案 0 :(得分:4)

基本思路是首先根据points对点进行排序,然后将$push跟进到数组中。这可确保按排序顺序插入元素。然后我们Operations of Array Types使用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" : "bruce@wayne.com",
    "points" : 4,
    "globalRank" : NumberLong(2)
}

/* 2 */
{
    "companyRank" : NumberLong(0),
    "name" : "Tony Stark",
    "company" : "Stark Industries",
    "email" : "tony@stark.com",
    "points" : 6,
    "globalRank" : NumberLong(1)
}

/* 3 */
{
    "companyRank" : NumberLong(0),
    "name" : "Clark Kent",
    "company" : "Daily Planet",
    "email" : "clark.kent@planet.com",
    "points" : 3,
    "globalRank" : NumberLong(3)
}

/* 4 */
{
    "companyRank" : NumberLong(1),
    "name" : "Lois Lane",
    "company" : "Daily Planet",
    "email" : "lois.lane@planet.com",
    "points" : 2,
    "globalRank" : NumberLong(4)
}

/* 5 */
{
    "companyRank" : NumberLong(0),
    "name" : "John Doe",
    "company" : "Acme",
    "email" : "john.doe@acme.com",
    "points" : 8,
    "globalRank" : NumberLong(0)
}

此处排名为0。

答案 1 :(得分:0)

您使用$ match条件。所以,你也试试这个..

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()

像这样的OutPut,

{
    "companyRank" : NumberLong(0),
    "name" : "Clark Kent",
    "company" : "Daily Planet",
    "email" : "clark.kent@planet.com",
    "points" : 3,
    "globalRank" : NumberLong(0)
}
{
    "companyRank" : NumberLong(1),
    "name" : "Lois Lane",
    "company" : "Daily Planet",
    "email" : "lois.lane@planet.com",
    "points" : 2,
    "globalRank" : NumberLong(1)
}

答案 2 :(得分: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" : "john.doe@acme.com",
                "points" : 8,
                "globalRank" : 1,
                "companyRank" : 1
        },
        {
                "_id" : 3,
                "name" : "Tony Stark",
                "company" : "Stark Industries",
                "email" : "tony@stark.com",
                "points" : 6,
                "globalRank" : 2,
                "companyRank" : 1
        },
        {
                "_id" : 2,
                "name" : "Bruce Wayne",
                "company" : "Wayne Enterprises",
                "email" : "bruce@wayne.com",
                "points" : 4,
                "globalRank" : 3,
                "companyRank" : 1
        },
        {
                "_id" : 4,
                "name" : "Clark Kent",
                "company" : "Daily Planet",
                "email" : "clark.kent@planet.com",
                "points" : 3,
                "globalRank" : 4,
                "companyRank" : 1
        },
        {
                "_id" : 5,
                "name" : "Lois Lane",
                "company" : "Daily Planet",
                "email" : "lois.lane@planet.com",
                "points" : 2,
                "globalRank" : 5,
                "companyRank" : 2
        }
]