[英]java mongodb 3.0: find value in internal array of documents
I'm using java and mongodb v.3.0.7. 我正在使用java和mongodb v.3.0.7。 I have a list of player with internal array of games with scores. 我有一个带有内部游戏分数的玩家列表。 This is a test that insert a document: 这是插入文档的测试:
public void insertPlayer(String id_device) throws ParseException{
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
db.getCollection("player").insertOne(
new Document()
.append("nikname", "Guest")
.append("password", "Guest")
.append("my_id", "")
.append("id_device", id_device)
.append("language", "Italian")
.append("games", asList(
new Document()
.append("gamename", "PPA")
.append("banned", false)
.append("date", format.parse("2014-10-01T00:00:00Z"))
.append("score", 11),
new Document()
.append("gamename", "Test2game")
.append("banned", false)
.append("date", format.parse("2014-01-16T00:00:00Z"))
.append("score", 17)))
);
}
To find if a player is banned from a particular game I'm doiing this: 要查找某个玩家是否被禁止参加特定游戏,我正在这样做:
public boolean isBanned(String id_device){
FindIterable<Document> iterable = db.getCollection("player").find(eq("id_device", "machine1"));
System.out.println(iterable.first());
List<Document> dl = (List<Document>)iterable.first().get("games");
for(int i=0;i<dl.size();i++){
Document d = dl.get(i);
System.out.println(d.getString("gamename"));
if(d.getString("gamename").equals("PPA")){
boolean ban = d.getBoolean("banned");
return ban;
}
}
There is a faster way using embedded mongodb methods that find the document: 有一种使用嵌入式mongodb方法查找文档的更快方法:
new Document()
.append("gamename", "PPA")
.append("banned", false)
.append("date", format.parse("2014-10-01T00:00:00Z"))
.append("score", 11),
giving id_device and gamename? 提供id_device和游戏名? thanks 谢谢
To achieve that, you need to aggregate your data. 为此,您需要汇总数据。 https://docs.mongodb.org/manual/aggregation/ https://docs.mongodb.org/manual/aggregation/
Depending on your usecase, aggregation may change (more query, more pipeline steps). 根据您的用例,聚合可能会更改(更多查询,更多管道步骤)。
Here is your data: 这是您的数据:
{
"_id" : ObjectId("569a30a30586bcb40f7d2531"),
"my_id" : "",
"id_device" : "machine1",
"language" : "Italian",
"games" : [
{
"gamename" : "PPA",
"banned" : true,
"date" : ISODate("2014-10-01T00:00:00.000Z"),
"score" : 11
},
{
"gamename" : "Test2game",
"banned" : false,
"date" : ISODate("2014-01-16T00:00:00.000Z"),
"score" : 17
}
]
}
I assume: 我假设:
You have a list of unique players. Each of them play unique games.
(Example: player1 never plays PPA twice)
So, you need to search a game where the player is banned and return
all information for that game.
The aggregation would be: 聚合为:
db.player.aggregate([
{$match:{ "id_device" : "machine1"}},
{$unwind: "$games"},
{$match:{ "games.gamename" : "PPA", "games.banned" : true}}
])
Result 结果
[
{
"_id" : ObjectId("569a30a30586bcb40f7d2531"),
"my_id" : "",
"id_device" : "machine1",
"language" : "Italian",
"games" : {
"gamename" : "PPA",
"banned" : true,
"date" : ISODate("2014-10-01T00:00:00.000Z"),
"score" : 11
}
}
]
Some difference, if your players may play same game more than once (different date), you can change your aggregation pipelines. 有所不同,如果您的玩家可能多次玩同一游戏(不同的日期),则可以更改聚合管道。
{
"_id" : ObjectId("569a30a30586bcb40f7d2531"),
"my_id" : "",
"id_device" : "machine1",
"language" : "Italian",
"games" : [
{
"gamename" : "PPA",
"banned" : false,
"date" : ISODate("2014-10-01T00:00:00.000Z"),
"score" : 11
},
{
"gamename" : "Test2game",
"banned" : false,
"date" : ISODate("2014-01-16T00:00:00.000Z"),
"score" : 17
},
{
"gamename" : "PPA",
"banned" : true,
"date" : ISODate("2014-04-18T00:00:00.000Z"),
"score" : 23
},
{
"gamename" : "Foo",
"banned" : true,
"date" : ISODate("2015-03-03T00:00:00.000Z"),
"score" : 2
},
{
"gamename" : "Foo",
"banned" : false,
"date" : ISODate("2015-04-28T00:00:00.000Z"),
"score" : 2
}
]
}
So to query id_device and gamename "PPA", we define our aggregation this way: 因此,要查询id_device和游戏名称“ PPA”,我们可以通过以下方式定义聚合:
db.player.aggregate([
{$match:{ "id_device" : "machine1"}},
{$unwind: "$games"},
{$match:{ "games.gamename" : "PPA"}},
{$group: {_id:{"_id":"$_id", "my_id":"$my_id", "id_device":"$id_device","language":"$language"}, "games" : {$push:"$games"}}},
{$project: {"_id":"$_id._id", "my_id":"$_id.my_id", "id_device": "$_id.id_device", "language":"$_id.language", "games":"$games"}}
])
Result: 结果:
[
{
"_id" : ObjectId("569a30a30586bcb40f7d2531"),
"games" : [
{
"gamename" : "PPA",
"banned" : false,
"date" : ISODate("2014-10-01T00:00:00.000Z"),
"score" : 11
},
{
"gamename" : "PPA",
"banned" : true,
"date" : ISODate("2014-04-18T00:00:00.000Z"),
"score" : 23
}
],
"my_id" : "",
"id_device" : "machine1",
"language" : "Italian"
}
]
As you see, you can add/modify pipeline steps and get desired result. 如您所见,您可以添加/修改管道步骤并获得所需的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.