Update array element in JAVA Spring mongo - java

{
"_id" : ObjectId("55d42e3a0b21449d07f9a8a6"),
"status" : 1,
"billList" : [
{
"id" : 123,
"status" : 1
},
{
"id" : 234,
"status" : 1
},
......
{
"id" : xxx,
"status" : 0 // only the final record has status = 0
}
]}
I have many billList record and I want to update status of the final record from 0 to 1 but don't know the id of it.
{
"id" : xxx,
"status" : 0 // only the final record has status = 0
}
to
{
"id" : xxx,
"status" : 1
}
How can I use JAVA Spring to do that? Thank you!

Please have a try on below sample solution
MongoClient c = new MongoClient();
//to get your db (Please replace "yourDB" with your db name)
MongoDatabase db = c.getDatabase("yourDB");
//to get your collection (Please replace "yourColl" with your collection name)
MongoCollection<Document> yourColl = db.getCollection("yourColl");
//search result list to be return
List<Document> result = new ArrayList<Document>();
//to get final record from billList
yourColl.find().projection(new Document("billList", new Document("$slice",-1))).into(result);
//Based on your snippet given, assume there is only 1 document return and to get that document. You can put a loop here if there are more than 1 documents return and to be update
Document resultToUpdate = result.get(0);
//Update status
yourColl.updateOne(new Document("_id",resultToUpdate.get("_id")).append("billList.id", resultToUpdate.get("billList.id")), new Document("$set",new Document("billList.$.status",1)));

Related

How can I retrieve all the values in a column in mongo db into a ArrayList?

This is the values of my data stored in mongo db. How am I able to retrieve all the data of "HomeTown" and store it all into a list? My list would contain AA, AA, BB, BB, etc... I want to use that array list to create a for loop of each Hometown.
Sample mongo data
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "AA" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "AA" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "BB" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "BB" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
How can I get all of the values of "HomeTown" in Java into an array? I am trying to create a for loop with the HomeTown Names. I am currently using mongodb dependency through Spring boot. I am not sure how would I implement mongodb into my java to use mongo db.
Attempt/Problem
I was able to retrieve mongodb values in a list using the following code. I am trying to convert this list to a arraylist.
public List<AppPortModel> getAppPortList() {
List<ApServerModel> objLst = mongoOperations.findAll(ApServerModel.class);
String[] apServerArray = new String[objLst.size()];
for(int i = 0; i < objLst.size(); i++) {
apServerArray[i] = objLst.get(i);
}
Error on objLst.get(i)
Type mismatch: cannot convert from ApServerModel to String
Attempt #2 Following Sagar Example
#Autowired
MongoOperations mongoOperations;
MongoCollection<ApServerModel> myCollection = **mongoOperations.getCollection("apAllCustomer");**
List<ApServerModel> result = myCollection.find().into(new ArrayList<>());
Error on mongoOperations.getCollection
Type mismatch: cannot convert from DBCollection to MongoCollection<ApServerModel>
Looks like you're using mongo 3.x driver.You'll need to use something like this.
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("mkoydb");
MongoCollection<Document> myCollection = db.getCollection("apAllCustomer");
List<Document> result = myCollection.find().into(new ArrayList<>());
Fix for Attempt 1:
public List<AppPortModel> getAppPortList() {
List<ApServerModel> objLst = mongoOperations.findAll(ApServerModel.class);
String[] apServerArray = new String[objLst.size()];
for(int i = 0; i < objLst.size(); i++) {
apServerArray[i] = objLst.get(i).getHomeTown();
}
Fix for Attempt 2:
DBCollection dbCollection = mongoOperations.findAll(AppServreModel.class, "apAllCustomer");
You can call toArray() which, intuitively, returns a List<DBObject>.
List<DBObject> myList = null;
DBCursor myCursor=myCollection.find(new BasicDBObject(),"HomeTown");
myList = myCursor.toArray();
if you are using java driver with version 3.0 and above you can also do
collection.find().projection(Projections.include("HomeTown"));
You can use projection to retrieve only required fields.
db.apAllCustomer.find( ..., { HomeTown: 1 } );
In Java it depends on the API you use. See this for Spring Data:
SpringData MongoDB Using projection
MongoDB-Java:
Restrict fields in Result

Retrieve all the documents matching the criteria in an array elements which is a subdocument

{
"_id" : ObjectId("577b54816081dd32cd3e2d60"),
"user" : ObjectId("577b54816081dd32cd3e2d5e"),
"journals" : [
{
"title" : "Journal Title2",
"desc" : "desx2",
"feeling" : 3,
"date" : ISODate("2016-07-05T06:32:45.404Z"),
"deleteFl" : true,
"_id" : ObjectId("577b548d6081dd32cd3e2d64")
},
{
"title" : "Journal Title3",
"desc" : "desx3",
"feeling" : 3,
"date" : ISODate("2016-07-05T06:49:00.156Z"),
"deleteFl" : false,
"_id" : ObjectId("577b585c6081dd32cd3e2d6d")
},
{
"title" : "Journal Title4",
"desc" : "desx4",
"feeling" : 3,
"date" : ISODate("2016-07-05T06:49:06.700Z"),
"deleteFl" : false,
"_id" : ObjectId("577b58626081dd32cd3e2d70")
}
]
}
Above is my document structure
now, I need all the journal documents whose deleteFl = false.
I tried in this way using Java Mongo driver
getDatabase().getCollection("journals").find(and(eq("user", user), eq("journals.deleteFl", false)));
but still it gives me back all the documents including "deleteFl": true. any help here ?
Actually, your query returns 1 document, because the data is inside 1 document. What you want is to limit the returning fields of a document (limit subdocuments).
Note: You can do that using elemMatch in the projection, to limit the fields returned by the query. But elemMatch will return just one subdocument. (I posted a deleted wrong answer using elemMatch)
When you want all subdocuments and only specific subdocuments from inside an array, you need to use the aggregation pipeline.
Here is a tested code that does what you want (just change DB and colelction name):
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection collection = db.getCollection("test");
Iterable<Document> output = collection.aggregate(asList(
new BasicDBObject("$unwind", "$journals"),
new BasicDBObject("$match", new BasicDBObject("journals.deleteFl", false))
));
for (Document dbObject : output)
{
System.out.println(dbObject);
}

How to get and update nested document in mongo db using java

I have a documents in mongo db as follows. I want to get and update the document having policyMap equals CostCalculation.In this CostCalculation has array format update in array elements such as 'policyName' have 'CostCalculationPolicyuserDefine' and set 'policyDes' = 'New Value' Please suggest the java code to solve this.
I searched mongo operartors but couldn't get it.
Sample mongo db document structure.
{
"policyMap" : {
"CostCalculation" : [{
"policyName" : "CostCalculationPolicyuserDefine",
"policyDesc" : "Priority user Defined Policy",
"userDefined" : 1
},
{
"policyName" : "CostCalculationPolicyuserDefine1",
"policyDesc" : "Priority user Defined Policy",
"userDefined" : 1
}]
},
"bsVer" : 2,
"bsFlag" : true,
"crBy" : "xxxxx",
"crDate" : NumberLong("1440138385345"),
"entNm" : "xxxx"
}
{
"policyMap" : {
"CostValue" : [{
"policyName" : "CostValuePolicyuserDefine",
"policyDesc" : "Priority user Defined Policy",
"userDefined" : 1
},
{
"policyName" : "CostCalculationPolicyuserDefine1",
"policyDesc" : "Priority user Defined Policy",
"userDefined" : 1
}]
},
"bsVer" : 2,
"bsFlag" : true,
"crBy" : "xxxxx",
"crDate" : NumberLong("1440138385345"),
"entNm" : "xxxx"
}
My sample java code
DBCollection coll = db.getCollection("nestedtest");
BasicDBObject searchDocument = new BasicDBObject();
searchDocument.put( "policyMap ", new BasicDBObject("$exists", new BasicDBObject("$eq", "CostCalculation")));
coll.remove(searchDocument);
What would be the similar java code to get the correct result.
Thanks.
This code works using Mongo 3 java drivers. It removes the need for all the BasicDBObjects that are in your code:
MongoClientURI uri = new MongoClientURI("mongodb://localhost:27017");
MongoClient client = new MongoClient(uri);
initialiseCollection(client);
Bson filter = Filters.exists("policyMap.costCalculation");
client.getDatabase("test").getCollection("test").deleteOne(filter);
DBCollection coll = db.getCollection("minnalPolicyMetadata");
BasicDBObject searchDocument = new BasicDBObject();
searchDocument.put("policyMap.CostCalculation",new BasicDBObject("$exists",true));
DBCursor cursor = coll.find(searchDocument);
if(cursor.count() != 0){
while(cursor.hasNext())
System.out.println(cursor.next());
}
In this way i solved this problem.Use exists operator in mongo

BasicDBObject update duplicate same document

I have a big problem with the api java mongodb. I use a request with the update methods of DBCollection class and in the mongodb i get a multiple same document while the value doesn't change,help me please. I don't want to have a duplicate document.
BasicDBObject query = new BasicDBObject();
query.append("ad", "man2ist").append("list.id", new BasicDBObject("$ne", "5")); // "list.id" : {$ne : 0 }
BasicDBObject a = new BasicDBObject("id",String.valueOf(5)).append("value", 100);
BasicDBObject upd = new BasicDBObject("$addToSet",new BasicDBObject("list",a));
System.out.println(query);
System.out.println(upd);
WriteResult r = dbc.update(query,upd,true,false);
//db.friends.update({ "ad" : "man2ist" , "list.id" : { $ne : "4"} },{ $addToSet : { "list" : { "id" : "4","value" : 100}}},true,true);
my document here :
{
"ad" : "man2ist",
"createdDate" : ISODate(),
"list" : [
{
"id" : "45",
"value" : 489
},
{
"id" : "5",
"value" : 20,
},
{
"id" : "4578",
"value" : 21,
} ]}
The problem is that you set the upset flag to true, meaning that the document should be created if no document matching the criteria is found. If there is no document matching the criteria in the db, the mongo shell will do the same.
If you change your query to this,
WriteResult r = dbc.update(query,upd,false,false);
it should work all the time.

Update multiples fields Mongo DB

i have a big problem with mongo db because i want to update a multiple fields with One request.
My Json is :
db.test.findOne();
{
"_id" : ObjectId("51e7dd16d2f8db27b56ea282"),
"ad" : "noc2",
"list" : {
"p45" : {
"id" : "p45",
"date" : ISODate("2014-01-01T12:18:30.568Z"),
"value3" : 21,
"value1" : 100,
"value2" : 489
},
"p6" : {
"id" : "p6"
"date" : ISODate("2013-07-18T12:18:30.568Z"),
"value3" : 21,
"value1" : 100,
"value2" : 489
},
"p4578" : {
"id" : "4578"
"date" : ISODate("2013-07-18T12:18:30.568Z"),
"value3" : 21,
"value1" : 100,
"value2" : 489
}
}
}
I want created a field createdDate for all elements list , if createdDate field doesn't exist or is null.
A request example, what i use for update one field with upsert true in my code java :
db.people.update({"advertiser":"noc2","list.4578.createdDate":{$exists:false}},{$set:{"list.p4578.createdDate":"08/08/08"}});
I tried with java where list.4578 is replaced by variable but is too long for too much fields. If i have 100 fields, i do execute 100 requests.
Look :
public void createdFirstDateField(MongoAccess mongo, String ad,HashMap<String,Object> hfirstDate){
BasicDBObject searchQuery = new BasicDBObject();
Iterator <String> it = hfirstDate.keySet().iterator();
String key="";
while (it.hasNext()){
key=it.next();
searchQuery.append("ad", ad).append(key, new BasicDBObject("$exists", false));
//System.out.println(key);
BasicDBObject doc = new BasicDBObject ();
doc.append("$set",new BasicDBObject(key,new Date()));
mongo.insert(searchQuery, doc); // update with upsert true
}
}
Thanks.
Why don't you use the update with upsert?
db.people.update({"advertiser": "noc2"},
{$set: {"list.$.createdDate": "08/08/08"}},
{$upsert: true);
If the createdDate exists it will be updated, if not it will be inserted.
You can update multiple documents at once, using update Multi. But there in not atomic way to update multiple embedded documents.
You can checkout mongodb positional operator, but this does not fit in your use case.

Categories