mongodb & java update array - java

I want to do some kind of log tool.
my json structure will be like this.
{
_ObjectId:1
"sessionId":
"room":"oda1"
"roomType":
"attendees": {
{
"userObjectid":"1" ???
"userId":
"userDisplay":
"userAuthority":
"activities": {
{
"activity":"1" //1:joined
"timestamp":"1.1.1.1.1"
"result":"1"
},
{
"activity":"2" //2:disconnect
"timestamp":"1.1.1.1.1"
"result":"1"
},
}
},
{
"userObjectid":"1" ???
"userId":
"userDisplay":
"userAuthority":
"activities": {
{
"activity":"1" //1:joined
"timestamp":"1.1.1.1.1"
"result":"1"
},
{
"activity":"2" //2:disconnect
"timestamp":"1.1.1.1.1"
"result":"1"
},
}
}
}
}
My code works fine when create data for the first time.
Data should be updated while user do some activities(like join,quit (A tuple should have all session data.))
while update the data my code create new tag with named activities.
{ROOM=testo#conference.demo.com.tr, ROOM_TYPE=null, SESSION_ACTIVE=true, USERS={ "0" : { "ACTIVITIES" : [ { "RESULT" : "1" , "ACTIVITY" : "quit" , "TIMESTAMP" : { "$date" : "2016-07-26T12:12:09.518Z"}}]} , "ACTIVITIES" : { "RESULT" : "1" , "ACTIVITY" : "join" , "TIMESTAMP" : "Tue Jul 26 15:11:51 EEST 2016"} , "USERID" : "535e7387" , "USER_AUTHORITY_TYPE" : "Owner" , "USER_DISPLAY_NAME" : "focus"}, _id=57975388a297be1c19460557}
Here is my update code:
try {
DBCollection table = connectDB().getCollection("SESSIONS");
BasicDBObject sessionDetail = new BasicDBObject();
sessionDetail.put("ROOM", room);
sessionDetail.put("SESSION_ACTIVE", true);
sessionDetail.put("USERS.USERID", userName);
Map<String, Object> activityDetail = new HashMap<String, Object>();
//BasicDBObject activityDetail = new BasicDBObject();
activityDetail.put("ACTIVITY", "quit");
activityDetail.put("TIMESTAMP", new Date());
activityDetail.put("RESULT", "1");
BasicDBObject data = new BasicDBObject();
data.put("$push", new BasicDBObject("USERS.0.ACTIVITIES", activityDetail));
table.update(sessionDetail, data,true,true);
Also i get error change "USERS.0.ACTIVITIES" to "USERS.ACTIVITIES". Why 0 is necessary for this?
i do many research but couldn't find solution about it.
Could anyone help me please ?

Related

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

creating dynamically group query in java

I have the following database:
{ stream :{ "name": "name1",
"error1": 1,
"error2": 1,
"error3": 1 }
}
,
{ stream : {"name": "name1",
"error1": 2,
"error2": 1,
"error3": 1 }
}
,
{ stream : {"name": "name2",
"error1": 1,
"error2": 1,
"error3": 1 }
}
I would like to group it by name and sum every time some different combination of errors.
this is what I did in mongo, I need to create the following query dynamically in java
db.collection.aggregate([{$group: {_id: "$stream.name",error1: {$sum:"$stream.error1" },error2: {$sum: "$stream.error2" }} ])
the thing is that every time I need different combinations of the errors:error1 with error2, only error 1 etc..
this is what I did: (the arguments in the "if" are some boolean values that I am getting)
List<String> totalError = new ArrayList<String>();
BasicDBObject group = new BasicDBObject( "$group", new BasicDBObject("_id","$stream.name" ));
if (error1)
{
group.append("error1",new BasicDBObject ("$sum", "$stream.error1" ));
}
if (error2)
{
group.append("error2",new BasicDBObject ("$sum", "$stream.error2" ));
}
if (error3)
{
group.append("error3",new BasicDBObject ("$sum", "$stream.error3" ));
}
the problem is that I am getting:
{ "$group" : { "_id" : "$stream.name"} , "error1" : { "$sum: "$stream.error1"} , "error2" : { "$sum" : "$stream.error2"}
},
instead of:
{ "$group" : { "_id" : "$stream.name", "error1" : { "$sum: "$stream.error1"} , "error2" : { "$sum" : "$stream.error2"}}
if I knew what error combination I need I could use append in the constructor of group dbobject.. but I don't know the combination and I need to use the "ifs"
Try
BasicDBObject fields = new BasicDBObject("_id","$stream.name" );
if (error1)
fields.append("error1",new BasicDBObject ("$sum","$stream.error1"));
if (error2)
fields.append("error2",new BasicDBObject ("$sum","$stream.error2"));
if (error3)
fields.append("error3",new BasicDBObject ("$sum","$stream.error3"));
BasicDBObject group = new BasicDBObject( "$group", fields);
You should use helper functions when possible.
List<BsonField> fieldAccumulators = new ArrayList<>();
if (error1)
fieldAccumulators.add(Accumulators.sum("error1","$stream.error1"));
if (error2)
fieldAccumulators.add(Accumulators.sum("error2","$stream.error2"));
if (error3)
fieldAccumulators.add(Accumulators.sum("error3","$stream.error3"));
collection.aggregate(Arrays.asList(Aggregates.group("$stream.name", fieldAccumulators)));

Mongodb - update specific array element

I have a collection "prefs" with document structure as below
{
_id: {
userId: "abc"
},
val: {
status: 1,
prefs: [
{
value: "condition",
lastSent: ISODate("2017-07-17T23:46:53.717Z")
}
],
deal: 2,
prevDeal: 3
}
}
I am trying to update the date field lastSent with a condition on userId and status. Below are the queries that I derieved from my Java code.
Select Query:
{ "_id" : { "userId" : "abc"} , "val.status" : 1 , "val.prefs.value" : "condition"}
Update Query:
{ "$set" : { "val.prefs.$.lastSent" : { "$date" : "2017-07-17T23:50:07.009Z"}}}
The above query is giving error as follows:
The dotted field 'prefs.$.lastSent' in 'val.prefs.$.lastSent' is not valid for storage.
How do I achieve this?
Below is my Java code:
BasicDBObject _idObject = new BasicDBObject();
_idObject.put("userId", "abc");
BasicDBObject _selectQuery = new BasicDBObject();
_selectQuery.put("_id", _idObject);
_selectQuery.put("val.status", 1);
_selectQuery.put("val.prefs.value", "condition");
BasicDBObject _valueUpdateQuery = new BasicDBObject();
_valueUpdateQuery.put("prefs.$.lastSent", lastSent);
BasicDBObject _updateQuery = new BasicDBObject();
_updateQuery.put("$set", new BasicDBObject("val", _valueUpdateQuery));
prefs.update(_selectQuery, _updateQuery, true, true);
I just tested with your code in mongo shell this codes works fine you don't have to mention
$date
and i used this code for updating date
db.getCollection('tester').update({ "_id" : { "userId" : "abc"} , "val.status" : 1 , "val.prefs.value" : "condition"},{ "$set" : { "val.prefs.$.lastSent" : new Date()}})

Update a nested document filed and increment in mongodb

I want to update a nested document filed if present increment an old value with new value or insert a new document.
Data
New Zealand,Waikato,Hamilton,1004
New Zealand,Waikato,Auckland,145
New Zealand,Otago,Dunedin,1068
Json
{ "_id" : ObjectId("55e7d2a72f68907c17cfcb2f"), "country" : "New Zealand",
"regions" : [ { "region" : "Waikato", "size" : 1004 },
{ "region" : "Waikato", "size" : 145 }, { "region" : "Otago", "size" : 1068 } ] }
In document regions array is dynamic in nature. In above document I need to update an increment field size value of ~Waikato`. Instead of putting an another record in array of regions.
My code
BasicDBObject query = new BasicDBObject();
query.put("country", "New Zealand");
query.put("regions.$.region", "Waikato");
BasicDBObject data = new BasicDBObject().append("$inc", new BasicDBObject().append("regions.$.size", 145));
BasicDBObject command = new BasicDBObject();
command.put("$set", data);
collection.update(query, command, true, false);
I need output like these:
{ "_id" : ObjectId("55e7d2a72f68907c17cfcb2f"), "country" : "New Zealand", "regions" : [ { "region" : "Waikato", "size" : 1149 }, { "region" : "Otago", "size" : 1068 } ] }
Please suggest me on these issue.
Your positional $ operator only belongs in the "update portion and not the query. Also you need to .append() in the query otherwise you overwrite:
BasicDBObject query = new BasicDBObject();
query.put("country", "New Zealand");
query.append("regions.region", "Waikato");
BasicDBObject update = new BasicDBObject()
.append("$inc", new BasicDBObject().append("regions.$.size", 145));
collection.update(query, update, true, false);
Basically looks like this ( shell wise ) :
collection.update(
{ "country": "New Zealand", "regions.region": " "Waikato" },
{ "$inc": regions.$.size": 145 },
true,
false
)

Query from Vava to MongoDB: find event in a specific date range

I've got the following document in MongoDB:
{
"_id" : NumberLong(44),
"_class" : "la.test.app.server.model.Event",
"orgId" : NumberLong(2),
"typeCode" : 1,
"title" : "Test for notification",
"shortDescription" : "Test for notification",
"description" : "Test for notification",
"price" : "100",
"startDate" : ISODate("2015-02-08T16:30:07.000Z"),
"endDate" : ISODate("2015-02-09T16:00:07.000Z"),
"deleted" : false
}
I need to find this event among all others.
I'm trying to do such a simple thing with method:
public List<Event> getPendingEvents(Date start, Date end) {
return mongoOperations.find(
Query.query(Criteria
.where("startDate").gte(start).lte(end)
.and("typeCode").is("1")),
Event.class
);
That assembles and returns me query:
{
"startDate" : { "$gte" : { "$date" : "2015-02-08T05:29:00.000Z"} ,
"$lte" : { "$date" : "2015-02-08T05:31:00.000Z"}} ,
"typeCode":"1"
}
And this query finds just "Fields: null, Sort: null":
But a direct query to MongoDB:
db.events.find({
"startDate" : {"$gte" : ISODate("2015-02-08 16:30:07.000Z"),
"$lt" : ISODate("2015-02-08 16:31:07.000Z")},
"typeCode" : 1})
Finds the required event.
Did you tried by formating the date by using SimpleDateFormat...?
I had tried this long back...
// Find documents by date of birth
Date gtDate = null;
try {
gtDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse("1984-05-010T8:30:00.000Z");
} catch (ParseException e) {
e.printStackTrace();
}
BasicDBObject dateQueryObj = new BasicDBObject("DateOfBirth", new BasicDBObject("$lt", gtDate));
cursor = documents.find(dateQueryObj);
while(cursor.hasNext()) {
System.out.println("\n Find documents by date of birth. \n");
System.out.println(cursor.next());
}
Same problem was solved by using BasicDBObject instead of a mongoOperations intreface.
Something like that:
BasicDBObject query = new BasicDBObject();
query = new BasicDBObject("endDate", new BasicDBObject("$gte", start).append("$lte", end)).append("typeCode", 1);
List<DBObject> result = collection.find(query).toArray();

Categories

Resources