java - MongoDB聚合不能使用$limit两次

标签 java mongodb aggregation-framework jongo

我有以下 MongoDB 集合“Games”:

{ 
"_id" : ObjectId("515461d3c6c18efd4a811fd3"), 
"gameid" : NumberLong("86982207656"), 
"tableName" : "Hydra Zoom 40-100 bb", 
"nplayers" : 6, 
"playersList" : [   
                                    {           "exist" : true,         
                                                        "suspended" : false,
                                                        "grade" : 0,
                                                        "clusterId" : -1,
                                                        "playerid" : "DoomY9999",
                                                        "playsWithFriends" : 0,
                                                        "squeezePlay" : 0,
                                                        "weakShowdown" : 0,
                                                        "numberOfPlays" : 1
                                     },
                                  {
                                                        "exist": true,
                                                        "suspended" : false,

我想将以下 MySQL 查询映射到 MongoDB

String query = "SELECT idplayer, COUNT(idplayer) AS countplayer "
                    + "FROM (SELECT b.idgame, b.idplayer "
                    + "FROM associations a, associations b "
                    + "WHERE a.idplayer=? "
                    + "AND b.idgame=a.idgame "
                    + "AND b.idplayer <> ? "
                    + "ORDER BY b.idgame DESC LIMIT 1000) as c"
                    + " GROUP BY idplayer "
                    + "ORDER BY countplayer DESC LIMIT 5;";

查询说明:此 SQL 查询对与玩家“X”玩同一游戏的最频繁玩家进行计数。结果将是玩家的姓名和一起玩的次数

LIMIT 的简短说明:第一个“LIMIT 1000”实际上是我们要检查的游戏的限制,因为数据库可能非常大,我们只分析 DESC 中的最后 1000 个游戏顺序(最近的有更高的“gameid”)。

第二个限制5:针对“前5名”好友。我们将对他们的数字进行求和。

到目前为止,我已经完成了:聚合框架的几乎所有内容,但“ORDER BY b.idgame DESC LIMIT 1000) as c”除外。这对我来说很重要,因为它经历的比赛数量可能非常多。

这是我在 MongoDB(Java 驱动程序)中的查询:

 //build the query
    DBObject match1 = new BasicDBObject("$match", new BasicDBObject("playersList.playerid",_playerid));
    DBObject unwind = new BasicDBObject("$unwind", "$playersList");
    DBObject match2 = new BasicDBObject("$match", new BasicDBObject("playersList.playerid",new BasicDBObject("$ne",_playerid)));

    DBObject groupFields = new BasicDBObject("_id","$playersList.playerid");
    groupFields.put("times", new BasicDBObject("$sum",1));
    DBObject group = new BasicDBObject("$group", groupFields);
    DBObject sort = new BasicDBObject("$sort", new BasicDBObject("times",-1) );
    DBObject limit = new BasicDBObject("$limit", 5 );

    DBObject group2 = new BasicDBObject("$group", "gameid");
    DBObject sort2 = new BasicDBObject("$sort", new BasicDBObject("gameid",-1) );
    DBObject limit2 = new BasicDBObject("$limit", 1000 );

    DB db = mongoDb;
    DBCollection coll = db.getCollection("games");

    //aggregation query
    //THIS WORKS
    AggregationOutput output = coll.aggregate( match1, unwind, match2, group, sort, limit);

    //THIS DOESN'T WORK!
     AggregationOutput output = coll.aggregate( match1, unwind, match2, group, sort, limit, group2, sort2, limit2); 

请帮我解决这个问题。谢谢!

最佳答案

第一个 group 操作后,字段 game 不在结果中,因此第二个 group 操作基于该字段游戏无法运行。

为了实现更高效的查询,您应该重新排序聚合操作以尽早减少数据。我在展开玩家列表之前移动了游戏的匹配,并且不需要第二组。

在mongo shell中聚合操作是这样的:

// playerId to search for coplayers
var playerId = "DoomY9999"

db.game.aggregate([
    // First $match can take advantage of suitable index if available

    // Find all games that playerid X has played
    { $match : { "playersList.playerid" : playerId } },

    // Sort by most recent games (gameid descending)
    { $sort : { "_id.gameid" : -1 } },

    // Limit number of games to examine
    { $limit : 1000 },

    // Create a stream of documents from the playersList array
    { $unwind : "$playersList" },

    // Match players except for playerid X
    { $match : { "playersList.playerid" : {$ne : playerId }} },

    // Count number of games each player has played
    { $group : {
        _id : "$playersList.playerid",
        count : { $sum : 1 }
    }},

    // Sort by most frequent players (count descending)
    { $sort : { "count" : -1 } },

    // Limit results to 5 players
    { $limit : 5 },

    // Rename the result fields
    { $project : {
        _id : 0,
        coplayer : "$_id",
        count : 1
    }}
])

关于java - MongoDB聚合不能使用$limit两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15704540/

相关文章:

java - 将 Java 嵌套类转换为 Xamarin.Android

java - JDialog 永远不会被垃圾回收

java - 获取文件子路径的最佳方法

java - 无法使用 Fresco 从 Google Cloud Storage 加载公共(public)图像

Java - 访问在 Windows Azure 上运行的 MongoDB 服务器

node.js - 为什么我们应该使用 mongoose ODM 而不是直接使用 Mongodb 和 Nodejs/Express 的 mongodb 驱动程序?

mongodb - mongo $unwind 和 $group

MongoDB 到 AWS Redshift

mongodb - 在 mongodb 中相乘说只对字符串类型进行操作

mongodb - 为什么匹配聚合查询中的日期被忽略?