update a document in mongoDB using JAVA - mongodb

I'm just starting to learn mongoDB using JAVA. I have the the following document in mongo
{
"_id": {
"$oid": "513fa587c5d0cf174eb9b1f8"
},
"suitename": "test_suite_name",
"testname": "test_name]",
"milestones": [
{
"milestone_id": 45
}
]
}
I have a compound key on suitename, testname, and milestone_id. I have to process a file which has these three fields. I create a simple DBObject query and check if count != 0
BasicDBObject query = new BasicDBObject();
query.put("suitename", testsuite);
query.put("testname", testcase);
query.put("milestones.milestone_id", SampleProgram.milestone_id);
If count == 0 --> add document in mongo -> this seems to work fine
What I am trying to figure out is:
If I have a new value of milestone_id in my file, I just need to add a milestone to some existing document's milestone array. Existing document is determined based on suitename AND testname.
So if milestone_id = 10, the document should look like
{
"_id": {
"$oid": "513fa587c5d0cf174eb9b1f8"
},
"suitename": "test_suite_name",
"testname": "test_name]",
"milestones": [
{
"milestone_id": 45
},
{
"milestone_id": 10
}
]
}
How can I accomplish this?
Thanks

This can be accomplished with the $push operator which appends values to an array and the update(…) method.
BasicDBObject query = new BasicDBObject();
query.put("suitename", testsuite);
query.put("testname", testcase);
BasicDBObject push = new BasicDBObject();
push.put("$push",
new BasicDBObject("milestones",
new BasicDBObject("milestone_id", SampleProgram.milestone_id)));
yourCollection.update(query, push);

BasicDBObject newDocument = new BasicDBObject();
newDocument.append("$set", new BasicDBObject().append("clients", 110));
BasicDBObject searchQuery = new BasicDBObject().append("hosting", "hostB");
collection.update(searchQuery, newDocument);

Related

Intersect in mongodb from two records

MongoDb + Spring boot + intersectsArrays
I want to fetch randomly 15 users and know there common interest. Document structure is something like this
{
"_id": {
"$oid": "593f773202338a47584b351e"
},
"interests": [
{
"_id": {
"$oid": "5957933cf3c5f5253ec9476c"
},
"name": "abc1",
"facebookId": "123"
}]
]
}
Need to fetch common interest for each user returned by mongo.
Below is my Spring boot code
Criteria criteria = new Criteria().andOperator(Criteria.where("lastLoginDate").gte(Utility.getDateBeforeDays(lastLoginNewerThan)));
Aggregation agg = Aggregation.newAggregation(new CustomAggregationOperation(maxRecords),
Aggregation.match(criteria),Aggregation.project("id","name")
);
AggregationResults<Users> userResults = operations.aggregate(agg, Users.class, Users.class);
List<Users> users = userResults.getMappedResults();
Looks like Spring Mongo Data api doesn't provide a way to pass a list of values as input to the set intersection operator.
You can use AggressionExpression to provide custom implementation.Include below projection in project stage.
.and(new AggregationExpression() {
#Override
public DBObject toDbObject(AggregationOperationContext context) {
return new BasicDBObject("$setIntersection",
Arrays.<Object> asList(
Arrays.<Object> asList("reading","movies"),
"$interests"));
}
}).as("commonInterests"));
You can wrap the expression as a lambda for Java 8
and(context -> new BasicDBObject("$setIntersection",
Arrays.<Object> asList(
Arrays.<Object> asList("reading","movies"),
"$interests")))
.as("commonInterests");

modify array element's value with Java MongoDB driver

I want to modify array element using Java MongoDB driver. I am able to insert new pair to the array, but can't modify value corresponding to particular key.
How can I increase a by 2 in dummy array for document
{ "_id" : ObjectId("57a87614d03a435e4be44bb9"), "dummy" : [ { "a" : 1 }, { "b" : 5 } ] }
using Java MongoDB driver?
Here is what I've tried
BasicDBObject query = new BasicDBObject();
query.put("_id",doc_id_here);
BasicDBObject incValue = new BasicDBObject("dummy.$.a", 1);
BasicDBObject intModifier = new BasicDBObject("$inc", incValue);
coll.update(query, intModifier, false, false, WriteConcern.SAFE);
Your query in mongo shell
db.collection.update(
{ "_id": ObjectId("57a87614d03a435e4be44bb9") },
{ $inc: { "dummy.$.a": 1 } }
);
will result in error
The positional operator did not find the match needed from the query.
Unexpanded update: dummy.$.a
because in order to use positional $ operator for dummy array you need to set condition on this array in your query
db.collection.update(
{ "_id": ObjectId("57a87614d03a435e4be44bb9"), "dummy.a": { $exists: true } },
{ $inc: { "dummy.$.a": 1 } }
);
and then it will increment a as you expect.
With Java MongoDB driver it will be
BasicDBObject query = new BasicDBObject();
query.put("_id", new ObjectId("57a87614d03a435e4be44bb9"));
query.put("dummy.a", new BasicDBObject("$exists", true));
BasicDBObject incValue = new BasicDBObject("dummy.$.a", 1);
BasicDBObject intModifier = new BasicDBObject("$inc", incValue);
coll.update(query, intModifier, false, false, WriteConcern.SAFE);
Advice: before trying to construct your query with Java MongoDB Driver first try if it works in mongo shell.

MongoDb isDeleted attribute - not always exist

When fetching records in mongoDb using QueryBuilder:
DBObject query = QueryBuilder.start("field1).is("foo").and("field2").is("bar").get();
Sometimes isDeleted attribute will be on the record,
But sometimes it will not be there,
How do I use QueryBuilder to tell MongoDb to fetch records where isDeleted attribute is not true, or not there..
Using expressions I can do:
myOr.add(new BasicDBObject("isDeleted", bool));
myOr.add(new BasicDBObject("isDeleted", new BasicDBObject("$exists", bool)));
DBObject query = baseFilter.append("$or", myOr);
You essentially want the following mongodb query
var query = {
"$or": [
{ "isDeleted": false },
{ "isDeleted": { "$exists": false } }
]
}
db.collection.find(query)
Using the QueryBuilder, this will translate to
QueryBuilder query = new QueryBuilder();
query.or(
QueryBuilder.start("isDeleted").is(false).get(),
QueryBuilder.start("isDeleted").exists(false).get()
);
DBCursor cursor = collection.find(query.get());

Fetch mongo documents based on date

We are inserting mongo documents with identifier and there is a subarray within the documents.
insert 1 :
db.test.insert(
{
"companyId" : "123",
"persons" : [
{
"joiningDate" : NumberLong("1431674741623"),
"name" : "Rajesh"
}
],
})
insert 2 :
db.test.insert(
{
"companyId" : "123",
"persons" : [
{
"joiningDate" : NumberLong("1431674741653"),
"name" : "Rahul"
}
],
})
I would like to retreive the company details based on the company id and merge the persons into one array list, and sort the persons based on the joining date.
Currently I am able to retreive the data using QueryBuilder but I am unable to sort the person based on the date.I can use java comparator to do the same , but I am looking out if there is any API from mongo db java driver which can be used to get the same.
Thanks.
you should use mongo aggregation like first $unwind persons array and then sort persons.joiningDate and then group with push as below :
db.test.aggregate({
"$match": {
"companyId": "123" // match companyId
}
}, {
"$unwind": "$persons" //unwind person array
}, {
"$sort": {
"persons.joiningDate": -1 //sort joining date
}
}, {
"$group": {
"_id": "$companyId",
"persons": {
"$push": "$persons" //push all sorted data into persons
}
}
}).pretty()
For converting this code into java use mongo java aggregation as
// unwind persons
DBObject unwind = new BasicDBObject("$unwind", "$persons");
// create pipeline operations, with the $match companyId
DBObject match = new BasicDBObject("$match", new BasicDBObject("companyId", "123"));
// sort persons by joining date
DBObject sortDates = new BasicDBObject("$sort", new BasicDBObject("persons.joiningDate", -1)); // -1 and 1 descending or ascending resp.
// Now the $group operation
DBObject groupFields = new BasicDBObject("_id", "$companyId");
groupFields.put("persons", new BasicDBObject("$push", "$persons"));
DBObject group = new BasicDBObject("$group", groupFields);
// run aggregation
List < DBObject > pipeline = Arrays.asList(match, unwind,sortDates, group);
AggregationOutput output = test.aggregate(pipeline);
for(DBObject result: output.results()) {
System.out.println(result);
}

Find objects by array in mongodb (or java)

I've got a collection (dataset) like this:
{
"_id" : ObjectId("515611c1c6e3718ee42a5655"),
"id": "Product1",
"type": "ProductType4"
"productFeature": [
{
"id": "ProductFeature1"
},
{
"id": "ProductFeature2"
},
{
"id": "ProductFeature3"
}
]
"productPropertyNumeric": 25
},
... and more product objects...
{
"_id" : ObjectId("515611c1c6e3718ee42a5666"),
"id": "ProductFeature1",
"label": "blablabla"
},
{
"_id" : ObjectId("515611c1c6e3718ee42a5667"),
"id": "ProductFeature2",
"label": "blebleble"
},
{
"_id" : ObjectId("515611c1c6e3718ee42a5668"),
"id": "ProductFeature3",
"label": "blublublu"
} ... and more feature objects...
According to Product1, I have to find the features and labels that the specific product has in its "productFeature" array.
I have tried in Mongo shell to find them (using a variable, for example):
var aaa = db.dataset.find({ id: "Product1" })
db.dataset.find({ id: "aaa.productFeature.id" })
But it doesn't work. If somebody knows how to find objects by array please help me.
Thanks very much.
PS: It would be best in Java - I apply a query just for example:
BasicDBObject query = new BasicDBObject();
query.put("type","ProductType4");
query.put("productPropertyNumeric", new BasicDBObject("$gt", 10));
DBCursor cursor = coll.find(query).sort( new BasicDBObject("label", 1));
while (cursor.hasNext()){
System.out.println(cursor.next().get("id"));
}
Here is my answer to my own question. I hope this helps to someone.
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
query.put("id", "Product1");
field.put("id", 1);
field.put("productFeature", 1);
field.put("_id", 0);
DBCursor cursor = coll.find(query, field);
while (cursor.hasNext()) {
BasicDBObject result = (BasicDBObject) cursor.next();
System.out.println(result);
ArrayList<BasicDBObject> features = (ArrayList<BasicDBObject>) result.get("productFeature");
for (BasicDBObject embedded : features) {
String featuresId = (String) embedded.get("id");
BasicDBObject query2 = new BasicDBObject();
BasicDBObject field2 = new BasicDBObject();
query2.put("id", featuresId);
field2.put("id", 1);
field2.put("label", 1);
field2.put("_id", 0);
DBCursor cursor2 = coll.find(query2, field2);
while (cursor2.hasNext()) {
System.out.println(cursor2.next());
}
}
}
You have to supply the "path" in the document structure to the field you want to query on from the document root. In this case the path is 'productFeature' --> 'id'. Instead of an arrow MongoDB uses a dot (.), e.g.,
db.dataset.find({ "productFeature.id" : "Product1" });
In Java you do something very similar:
BasicDBObject query = new BasicDBObject("productFeature.id" : "Product1");
DBCursor cursor = coll.find(query).sort( new BasicDBObject("label", 1));
while (cursor.hasNext()){
System.out.println(cursor.next().get("id"));
}
In Java you could also use the Query class in combination with MongoTemplate.
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
#Autowired
private final MongoTemplate mongoTemplate;
...
public YourObjectClass findProduct1(){
Query query = new Query();
query.addCriteria(Criteria.where("productFeature.id").is("Product1"));
List<YourObjectClass> result = this.mongoTemplate.find(query, YourObjectClass.class);
return result;
}