Mongodb Aggregate Date match in Java - java

I have below Mongo DB aggregate query which is giving me the below output
Sample Documents in Mongodb
/* 4 */
{
"_id" : ObjectId("5a536d89e5b8f73d4e41ba96"),
"name" : "yyyyy",
"creationDate" : ISODate("2018-01-02T16:27:25.201Z"),
"address" : "xxx",
"zipcode" : "10254"
}
/* 5 */
{
"_id" : ObjectId("5a536d95e5b8f73d4e41ba97"),
"name" : "zzzzz",
"creationDate" : ISODate("2018-01-03T16:28:25.201Z"),
"address" : "xxx",
"zipcode" : "10254"
}
Aggregate Query
db.test_customer.aggregate([
{$match:{creationDate:{"$gte":ISODate("2018-01-01"),"$lt":ISODate("2018-01-05")}}},
{$project:{"_id":"$_id","name":"$name",creationDate:"$creationDate"}},
{$group:{"_id":"$_id",customer:{"$push":"$$ROOT"}}}
])
This gives me below result
/* 1 */
{
"_id" : ObjectId("5a536d95e5b8f73d4e41ba97"),
"customer" : [
{
"_id" : ObjectId("5a536d95e5b8f73d4e41ba97"),
"name" : "zzzzz",
"creationDate" : ISODate("2018-01-03T16:28:25.201Z")
}
]
}
/* 2 */
{
"_id" : ObjectId("5a536d89e5b8f73d4e41ba96"),
"customer" : [
{
"_id" : ObjectId("5a536d89e5b8f73d4e41ba96"),
"name" : "yyyyy",
"creationDate" : ISODate("2018-01-02T16:27:25.201Z")
}
]
}
When i try to convert to Java coding i am not getting the output. it is returning empty result
My Java code
DBCollection collection = mongoTemplate.getCollection("test_customer");
DBObject match = new BasicDBObject("$match", new BasicDBObject("creationDate", new BasicDBObject("$gte", getDate("01/01/2018")).append("$lt", getDate("05/01/2018"))));
DBObject project = new BasicDBObject("$project", new BasicDBObject("_id", "$_id").append("name", "$name").append("creationDate", "$creationDate"));
DBObject group = new BasicDBObject("$group", new BasicDBObject("_id", "$_id").append("customer", new BasicDBObject("$push", "$$ROOT")));
AggregationOutput aggregate = collection.aggregate(Arrays.asList(match, project, group));
Iterable<DBObject> results = aggregate.results();
for (DBObject obj : results) {
String obj1 = (String) obj.toString();
System.out.println(obj1);
}
private Date getDate(String date) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date1 = sdf.parse(date);
return date1;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
My Java code is creating aggregate query like below
db.test_customer.aggregate([
{ "$match" : { "creationDate" : { "$gte" : { "$date" : "2017-12-31T18:30:00.000Z"} , "$lt" : { "$date" : "2018-01-04T18:30:00.000Z"}}}},
{ "$project" : { "_id" : "$_id" , "name" : "$name" , "creationDate" : "$creationDate"}},
{ "$group" : { "_id" : "$_id" , "customer" : { "$push" : "$$ROOT"}}}
])
I don't know why $date is not picking the ISODate in mongodb. Please suggest me how to use aggregate date condition in mongodb

Related

mongoTemplate returning unformatted object

I have following aggregation query method:-
public List<String> fetchRelativeIds(String externalId) {
ProjectionOperation projectionOperation = project().and("ancestors._id")
.concatArrays("descendants._id").as("weNeedRelations").andInclude("_id");
MatchOperation filterByIds = Aggregation.match(new Criteria("externalIds.fenergo").is(externalId));
Aggregation aggregation = newAggregation(filterByIds, projectionOperation);
return mongoTemplate.aggregate(aggregation, Master.class.getSimpleName(), String.class).getMappedResults();
}
This gives me output as below:-
{ "_id" : { "$oid" : "5aafb705f3fabe7c915bca14"} , "weNeedRelations" : [ { "$oid" : "5aafb718f3fabe7c915bca1f"} , { "$oid" : "5aafb719f3fabe7c915bca23"} , { "$oid" : "5aafb6fbf3fabe7c915bca10"}]}
I just want the $oid value part as string nothing else. E.g.
{ "_id" : "5aafb705f3fabe7c915bca14" , "weNeedRelations" : [ "5aafb718f3fabe7c915bca1f" , "5aafb719f3fabe7c915bca23", "5aafb6fbf3fabe7c915bca10"]}
How could I do that?

How to pass list of generic fields with their corresponding first operator to Aggregation.group method

I want to write a generic code for aggregation using mongoTempalte and Aggregation.group() method. So I have the problem of passing generic fields into the group method with the first() operator
here is my demo native query as follows:
db.subscriberProfile.aggregate([{"$unwind":"$usage_history"},
{ "$group" : { "_id" :"$_id" ,"birthdate" : { "$first":"$birthdate"} , "category" : { "$first":"$category"} , "control_group" : { "$first":"$control_group"} , "sumOfTotalUsage" : { "$sum" :{"$cond": [ { "$gte" :[ "$usage_history.date" , ISODate( "2017-01-13T10:43:55.306Z")] }, "$usage_history.total_usage", 0]}}}},
{ "$match" : { "$and" : [ { "birthdate" : { "$lte" : ISODate( "2017-07-12T10:43:55.306Z")}} , { "birthdate" : { "$gte" : ISODate( "1917-07-12T10:20:35.306Z")}} , { "category" : { "$in" : [ "Prepaid"]}} , { "control_group" : false} , { "sumOfTotalUsage" : { "$gte" : 0}}]}}])
And here is my Sample code in Java.
UnwindOperation unwind = Aggregation.unwind("usage_history");
GroupOperation group = Aggregation.group(fields.toArray(new String[fields.size()])).sum("usage_history.total_usage").as("sumOfTotalUsage");
I just want to know how to add multiple fields in group operation with $first operator.
So, Is there any way to pass list of fields with list of first operator to the group method.
Thanks,
Try this code,I hope this will help you
UnwindOperation unwind = Aggregation.unwind("usage_history");
BasicDBObject object = new BasicDBObject("_id", "$_id");
for (String string : fields) {
object.append(string, new BasicDBObject("$first", "$" + string));
}
object.append("total", new BasicDBObject("$sum", new BasicDBObject("$cond",
new Object[] { new BasicDBObject("$gte", new Object[] { "$usage_history.date", calendarMin.getTime() }),
"$usage_history.total_usage", 0 })));
BasicDBObject groupObject = new BasicDBObject("$group", object);
DBObject groupOperation = (DBObject) groupObject;
MatchOperation matchMain = Aggregation
.match(new Criteria().andOperator(criteriaList.toArray(new Criteria[criteriaList.size()])));
Aggregation aggregation = Aggregation.newAggregation(unwind, new CustomGroupOperation(groupOperation),
matchMain);

Java MongoClient - Type exceptions when using Aggregate

I am getting the following exception:
com.mongodb.CommandFailureException: { "serverUsed" : "192.168.3.25:27017" ,
"errmsg" : "exception: The argument to $size must be an Array,
but was of type: EOO" , "code" : 17124 , "ok" : 0.0}
Whenever I run this pipeline using the MongoClient driver for Java:
[{ "$match" : { "_id" : "1"}}, { "$project" : { "count" : { "$size" : "$tags"}}}]
What is causing this? The pipeline works fine in the Mongo shell?
Here is my Java code:
private void countArrayLength(String id, String arrayName) {
AggregationOptions options = AggregationOptions.builder().build();
DBObject matchFields = new BasicDBObject("_id", id);
DBObject match = new BasicDBObject("$match", matchFields);
DBObject projectCount = new BasicDBObject("$size", "$" + arrayName);
DBObject projectFields = new BasicDBObject("count", projectCount);
DBObject project = new BasicDBObject("$project", projectFields);
Cursor cursor = db.getCollection(collectionName)
.aggregate(asList(match, project), options);
}
DB Structure:
{
"_id" : "1",
"_class" : "com.mongodb.BasicDBObject",
"tags" : [
{
"tag" : "tagName"
},
{
"tag" : "tagName"
},
{
"tag" : "tagName"
},
{
"tag" : "tagName"
},
{
"tag" : "tagName"
}
]
}

How to construct basicdbobject query to delete deep array documnet?

I am having mongo document as below
"_id" : ObjectId("5072b33aa4e8dd3e359b8e94"),
"menus" : {
"5072b8dda4e8dd3e359b8ea8" :
{
"_id" : ObjectId("5072b8dda4e8dd3e359b8ea8"),
"description" : "hfghfgh",
"MenuItems" :
[
{
"name" : "dfgdfg",
"description" : "dgdfgd",
"_id" : ObjectId("5072b91ba4e8dd3e359b8eaa")
},
{
"name" : "fgdfgdf",
"description" : "gdfgg",
"_id" : ObjectId("5072bb92a4e8204e51de1084")
}
]
}
}
Actually i had tried to delete the following object in the menuItems
{
"name" : "fgdfgdf",
"description" : "gdfgg",
"_id" : ObjectId("5072bb92a4e8204e51de1084")
}
My query as follows but its not working.
BasicDBObject query=new BasicDBObject("_id",objectId("...");
BasicDBObject document = new BasicDBObject("menus.5072b8dda4e8dd3e359b8ea8.menuItems.$._id", ObjectId("5072bb92a4e8204e51de1084") );
BasicDBObject updateOps=new BasicDBObject("$pull", document);
I am having id of menuItems "_id" : ObjectId("5072bb92a4e8204e51de1084") , id of menus "_id" : ObjectId("5072b8dda4e8dd3e359b8ea8") and id of top level document "_id" : ObjectId("5072b33aa4e8dd3e359b8e94"),
BasicDBObject query=new BasicDBObject("_id",new ObjectId(".....");
BasicDBObject document = new BasicDBObject("menus.5072b8dda4e8dd3e359b8ea8.menuItems",
new BasicDBObject("_id":ObjectId("5072bb92a4e8204e51de1084") );
BasicDBObject updateOps=new BasicDBObject("$pull", document);
db.collection.update(query,updateOps);

Java equivalent of scala query in mongodb

What is the equivalent cde in Java:
var result = collectionName.findOne()
println(result.get("name").toString)
To elaborate, This is my sample db:
{ "_id" : ObjectId("4ca039f7a5b75ab98a44b149"), "name" : "kaustubh", "country" : "india" }
{ "_id" : ObjectId("4ca03a85a12344a5e47bcc5c"), "name" : "rahul", "country" : "pakistan" }
{ "_id" : ObjectId("4ca03a9ea12344a5e47bcc5d"), "name" : "swapnil", "country" : "lanka" }
{ "_id" : ObjectId("4ca03b19a12344a5e47bcc5e"), "name" : "sagar", "country" : "nepal" }
i am running the following query on it:
query.put("country", "india");
DBCursor cursor = collection.find(query);
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
that prints:
{ "_id" : { "$oid" : "4ca04b6b37a85ab92557218a"} , "name" : "kaustubh" , "country" : "india"}
as many times as the pair exists in the collection.
how do I formulate a query to get all the names, once and get the count for them.I read the docs, and didnt stumble upon any way to do it.
Try this
query.put("name", "kaustubh");
DBObject myDoc = collection.findOne(query);
System.out.println(myDoc);

Categories