Count document MongoDB java - java

I am new to MongoDB and I am finding rather complicated to count the child number of my nested documents.
This is part of my 'users' collection.
"_id" : ObjectId("58f9f7a91fb2bf7c46abe5d6"),
"name" : "fernando guima",
"premium" : true,
"email" : "lolol#loladamix.com",
"creationDate" : ISODate("2017-04-21T12:14:33.970Z"),
"playlists" : [
{
"name" : "minha Playlist",
"creationDate" : ISODate("2017-04-21T12:14:33.982Z"),
"videos" : [
{
"video_id" : "video1",
"creationDate" : ISODate("2017-04-21T13:00:38.461Z")
},
{
"video_id" : "video2",
"creationDate" : ISODate("2017-04-21T13:00:38.502Z")
}
]
},
{
"name" : "minha Playlist 2",
"creationDate" : ISODate("2017-04-21T12:14:33.983Z"),
"videos" : [ ]
}
]
}
I want to be able to retrieve the number of 'videos' in my 'playlist' (playlist childs) and retrieve a video data, how can I do that?
I wrote the following code that adds a video to a given playlist:
public void addToPlaylist(String parameter, String value, String playListName, String video_id){
//user document
BasicDBObject query = new BasicDBObject(parameter, value);
//First it fetches the wanted document by a parameter and its value e.g, (name, Fernando)
BasicDBObject mObject = new BasicDBObject();
mObject.put("video_id", video_id);
mObject.put("creationDate", new Date());
BasicDBObject updateObj = new BasicDBObject();
//falta percorrer o array das playlists para encontrar o id pelo nome da playlist
updateObj.put("$push", new BasicDBObject("playlists."+"0"+".videos", mObject));
mMongo.getCollection("users").updateOne(query, updateObj);
}
I expect to receive, {videos : 2} as the number of videos in my first playlist. And some output about video data like: {"video_id" : "video1"}
Regards

You can use below query. The query will $match to select the document followed by $unwind of playlists array and $project to reach videos array to calculate its $size and extract video_id.
MongoClient client = new MongoClient("localhost", 27017);
MongoDatabase database = client.getDatabase("db");
MongoCollection<Document> collection = database
.getCollection("collection");
Bson filter = Filters.eq("_id", new ObjectId("58f9f7a91fb2bf7c46abe5d6"));
List<VideoResult> results = collection.aggregate(Arrays.asList(Aggregates.match(filter), Aggregates.unwind("$playlists"), Aggregates.project(Projections.fields(Arrays.asList(Projections.computed("videos", new Document("$size","$playlists.videos")),
Projections.computed("video_ids", "$playlists.videos.video_id")))))).map(VideoResult::new).into(new ArrayList<>());
Output:
{
"_id" : ObjectId("58f9f7a91fb2bf7c46abe5d6"),
"videos" : 2,
"video_ids" : [
"video1",
"video2"
]
}
{
"_id" : ObjectId("58f9f7a91fb2bf7c46abe5d6"),
"videos" : 0,
"video_ids" : [ ]
}
Pojo:
public class VideoResult {
private int videos;
private List<String> videoIds;
public VideoResult(Document doc) {
this.videos = doc.getInteger("videos");
this.videoIds = (List<String>) doc.get("video_ids");
}
// getters and setters
}

Another solution, MongoDB 3.4
db.users.aggregate([
{$unwind: '$playlists'}, {$addFields: {'playlists.id': '$_id'}},
{$replaceRoot: {newRoot: '$playlists'}},
{$unwind: {path: '$videos', preserveNullAndEmptyArrays: true}},
{$group: {_id: {name: '$name', creationDate: '$creationDate', _id: '$id'},
video_ids: {$push: '$videos.video_id'},
videos: {$sum: {$cond: [{$ifNull: ['$videos', 0]}, 1, 0]}}}},
{$addFields: {_id: '$_id._id'}}])
Output:
{
"_id" : ObjectId("58f9f7a91fb2bf7c46abe5d6"),
"video_ids" : [ ],
"videos" : 0
}
{
"_id" : ObjectId("58f9f7a91fb2bf7c46abe5d6"),
"video_ids" : [
"video1",
"video2"
],
"videos" : 2
}

Related

How to get a String inside an Object Array using MongoDB Java?

I'm trying to learn MongoDB and I want to get a String inside an Object Array, my MongoDB document is here:
{
"_id" : ObjectId("5f1507fed91e81246c409a59"),
"identification" : "punishment",
"lastID" : 2,
"punishmentsTypes" : [
{
"category" : "OFENSA_JOGADOR",
"reason" : "Ofensa a Jogador",
"group" : [
"HELPER",
"MODERATOR",
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Ofender algum jogador",
"cases" : [
{
"1" : {
"type" : "MUTE",
"duration" : 604800000
}
},
{
"2" : {
"type" : "BAN",
"duration" : 0
}
}
]
},
{
"category" : "FALSIFICACAO",
"reason" : "Falsificação de provas",
"group" : [
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Falsicar provas ao denunciar um jogador em nosso fórum",
"cases" : [
{
"1" : {
"type" : "BAN",
"duration" : 0
}
}
]
},
{
"category" : "HACK",
"reason" : "Hack",
"group" : [
"MODERATOR",
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Uso de cheats ou programas ilícitos",
"cases" : [
{
"1" : {
"type" : "BAN",
"duration" : 7776000000.0
}
},
{
"2" : {
"type" : "BAN",
"duration" : 0
}
}
]
}
],
"unpunishmentTypes" : [
{}
]
}
I've tried this:
MongoCollection<Document> collection = mongoDatabase.getCollection("settings");
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
query.put("id", "punish");
field.put("punishmentsTypes", 1);
field.put("_id", 0);
Document test = collection.find(query).projection(field).first();
assert test != null;
Object object = test.get("punishmentsTypes");
System.out.println(object);
And that's the output:
[Document{{category=OFENSA_JOGADOR}},
Document{{category=FALSIFICACAO}}, Document{{category=HACK}}]
How can I get only the category string, to the output be: OFENSA_JOGADOR, FALSIFICACAO, HACK?
I'm not sure how did you get that result with your query but here is how I get your result:
MongoCollection<Document> collection = mongoDatabase.getCollection("settings");
Document query = new Document();
query.put("identification", "punishment");
Document test = collection.find(query).first();
List<Document> punishmentsTypes = test.getList("punishmentsTypes", Document.class);
for (Document document : punishmentsTypes) {
String category = document.getString("category");
System.out.println(category);
}

Push new object into an array of an existing document using MongoDB Java

I am trying to learn MongoDB and would like to know how I can insert POJO into existing collection. My collection looks exactly as below.
{
"_id" : ObjectId("5e930d68618c45b052492407"),
"game" : {
"team1" : [
{ "player" : "john", "age" : 25 },
{ "player" : "mick", "age" : 25 }
],
"team2" : [
{ "player" : "john", "age" : 25 },
{ "player" : "john", "age" : 25 }
]
}
}
Now I want to be able to insert a new player inside "team1" and the expected output should like the below,
{
"_id" : ObjectId("5e930d68618c45b052492407"),
"game" : {
"team1" : [
{ "player" : "john", "age" : 25 },
{ "player" : "mick", "age" : 23 },
{ "player" : "tom", "age" : 22 } //newly inserted
],
"team2" : [
{ "player" : "tony", "age" : 26 },
{ "player" : "bruce", "age" : 24 }
]
}
}
I have used POJO in java and my code is below,
Player object= new Player();
newPlayer.setPlayer("tom");
newPlayer.setAge(22);
BasicDBObject setQuery = new BasicDBObject();
setQuery.append("$push", object);
collection.updateOne(Filters.and(Filters.eq("_id", "5e930d68618c45b052492407"), Filters.eq("game.team1")), setQuery);
But the above seems not works and request to help me on this. Please excuse me if you find any mistakes on my question.Thanks in advance.
ok I have found solution by myself, for those who ended up here with same problem, here is the solution that I have found.
BasicDBObject query = new BasicDBObject();
query.put("_id", valueofId);
BasicDBObject push_data = new BasicDBObject("$push", new BasicDBObject("game.team1", object));
collection.findOneAndUpdate(query, push_data);
You can add a new sub-document (or object) to an array using the following code. This uses the Updates builder class:
Document newPlayer = new Document("player", "tom").append("age", 22);
Bson update = Updates.push("game.team1", newPlayer);
Bson filter = Filters.eq("_id", new ObjectId("5e930d68618c45b052492407"));
UpdateResult result = collection.updateOne(filter, update);

Need to update only particular element in an array of mongo in java

I want to update a particular element in an array of mongo with filters.
I have already tried having using BasicDBObject, but than not able to use filter as i have collection of type MongoCollection.
MongoCollection collection = db.getCollection(tnId);
Even tried:
FindIterable<Document> document = collection.find(new BasicDBObject("DocumentName", documentName) .append("Attributes.name", "Party 1" ).append("Attributes.value", 12) .append("Attributes.actualValue.initialValue", USA));
But in this case What I get is the whole record and than I have to iterate through each Attribute again.
mongo = new MongoClient("localhost", 27017);
MongoDatabase db = mongo.getDatabase(companyName);
MongoCollection collection = db.getCollection(tnId);
Actual data which I am passing is
{
"DocumentName" : "doc1",
"Attributes" : [
{
"name" : "Party 1",
"value" : 12,
"actualValue" : {
"initialValue" : "USA"
}
},
{
"name" : "Party 1",
"value" : 16,
"actualValue" : {
"initialValue" : "SYSTEM"
}
}
]
}
and I want to search attribute where actualValue is "USA" and Value of attribute is 12 and updated data should look like
{
"DocumentName" : "doc1",
"Attributes" : [
{
"name" : "Party 1",
"value" : 12,
"actualValue" : {
"initialValue" : "USA"
},
"updatedvalue" : {
"initialValue" : "USA",
"changedValue" : "Europe"
}
},
{
"name" : "Party 1",
"value" : 16,
"actualValue" : {
"initialValue" : "SYSTEM"
}
}
]
}
db.collection.findOneAndUpdate({ "Attributes.actualValue.initialValue": "USA" },
{ $set: { "Attributes.$.updatedvalue.initialValue": "USA", "Attributes.$.updatedvalue.changedValue": "Europe" } })
db.collection.findOneAndUpdate({ "Attributes.actualValue.initialValue": "USA" },
{ $set: { "Attributes.$.updatedvalue.initialValue": "India", "Attributes.$.updatedvalue.changedValue": "India" } })
Try with this one
db.collection.updateMany(
{ "Attributes.actualValue.initialValue": "USA" },
{ $set: { "Attributes.$.updatedvalue" : {
"initialValue" : "USA",
"changedValue" : "Europe"
} } }
)
How I did is. I made a document where i added teh required data which i want to update it with.Say
Document valueDocument = new Document();
valueDocument.put("InitialValue", USA);
BasicDBObject query = new BasicDBObject();
query.put("Attributes", att);
BasicDBObject data = new BasicDBObject();
data.put("Attributes.$.updatedvalue" + qCLevel, valueDocument);
BasicDBObject command = new BasicDBObject();
command.put("$set", data);
collection.updateOne(query, command);
It goes and insert the data in the right place.

MongoDB Query in Array of Arrays and add if not present

I have
{
"Districts" :
[{ "name" : "Krishna"
, "Locations" : [{ "name" : "Vijayawada"}
,{ "name" : "Machilipatnam"}]}
, { "name" : "Guntur"
, "Locations" : [{ "name" : "Satenpalli"}]}
]
, "_id" : 1
, "name" : "Andhra Pradesh"
}
I am trying to create one more Location "Achampet" if District name is "Guntur" so the result should be this below. The result should be the same even if I try to add Achampet more than once.
{
"Districts" :
[{ "name" : "Krishna"
, "Locations" : [{ "name" : "Vijayawada"}
,{ "name" : "Machilipatnam"}]}
, { "name" : "Guntur"
, "Locations" : [{ "name" : "Satenpalli"}
,{ "name" : "Achampet"}]}
]
, "_id" : 1
, "name" : "Andhra Pradesh"
}
But my java code doesn't work
DBObject newLoc = new BasicDBObject("Districts", new BasicDBObject("name", distName).append("Locations", new BasicDBObject("name", locName)));
if (statesColl.findOne(newLoc) == null) {
DBObject updateLoc = new BasicDBObject("$push", newLoc);
statesColl.update(queryDist, updateLoc);
}
It is creating a new District everytime I try to add a location. How can I fix this?
This is how you can do it using the $ positional operator in Java:
...
DBObject selectQuery = new BasicDBObject("_id", 1); // Matches the document
selectQuery.append("Districts.name", distName); // Matches the element in the array where District name = Guntur
BasicDBObject updateFields = new BasicDBObject();
updateFields.put("Districts.$.Locations", new BasicDBObject("name":"Achampet"));
DBObject updateQuery = new BasicDBObject("$addToSet", updateFields);
statesColl.update(selectQuery, updateQuery);
...

MongoDb accesing nested documents in java

I am new to MongoDB. I am trying to access nested doc in mongodb. My sample doc is
{
"Advertisement" : {
"html" : "zxcxz"
},
"Notification" : {
"date_from" : ISODate("2013-06-30T18:30:00Z"),
"date_too" : ISODate("2013-07-16T18:30:00Z"),
"description" : "vcvc",
"url" : "vcvc"
},
"_id" : ObjectId("51e4f10ee4b08e0a6ebcbe46"),
"group_name" : "sumit",
"target_audience" : {
"gender" : "male",
"section" : "xyz",
"catagory" : "--Computer--",
"location" : {
"country" : "--Country--",
"state" : "--State--",
"city" : "--City--"
}
}
}
I am trying to get gender from target_audience. My java code is
DBCursor f=con.coll.find(query);
while(f.hasNext())
{
f.next();
gender=(String) f.curr().get("target_audience.gender");
}
But it returns null.
The result of DBCursor.next() and DBCursor.curr() is a BasicDBObject. For keys with embedded documents, BasicDBObject.get(key) returns a BasicDBObject
DBCursor f=con.coll.find(query);
while(f.hasNext())
{
BasicDBObject result = (BasicDBObject) f.next();
BasicDBObject target = (BasicDBObject) result.get("target_audience");
gender = (String) target.get("gender");
}

Categories

Resources