我有以下 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/