MongoDB Java Driver: Aggregation using $match with multiple condition - java

I've been doing some search but haven't been able to find the answer. From docs, In mongo, if
$match: { type: "airfare"}
translated as:
DBObject match = new BasicDBObject("$match", new BasicDBObject("type", "airfare") );
in Mongo Java driver, how to translate this one into Mongo java driver?
$match : { score : { $gt : 70, $lte : 90 } }
EDIT
This is what I actually wanted to do:
$match : { bookingDateTime: { $gte : fromDate, $lte : toDate } }
And this is how implemented in mongodb java driver, with no luck so far:
DBObject matchFields2 = new BasicDBObject("$match", new BasicDBObject("bookingDateTime", new BasicDBObject("$gte", fromDate.getTime()).append("$lte", toDate.getTime())));
DBObject match2 = new BasicDBObject("$match", matchFields2);
fromDate is a Calendar object so hence the getTime() method to convert Calendar class to Date class.

Object match = new BasicDBObject("$match",
new BasicDBObject("score",
new BasicDBObject("$gt", 70).append("$lte", 90) ) )

Related

Spring Data MongoDB Aggregation Match with Date and average

I'm using mongoDB java driver to query transactions between date range and average of value with aggregate framework. This is my mongo query (it works):
db.campaignsForChatUsers.aggregate([{$match:{'created' :
{$gte : ISODate('2017-09-30T11:35:35.155Z'), $lt : ISODate('2019-09-30T11:35:35.155Z')}}},
{$group: {_id : "_id", aveTime: { $avg : "$details.nostradamusOfferCalculatingTime"}}}])
The java code I'm using to make query:
public Double getAverageTimeWithPeriod(){
MongoCollection<Document> dbCollection = mongoTemplate.getCollection(ChatUserCampaign.COLLECTION_NAME);
Date fromDate = LocalDate.parse("2019-10-01").toDate();
Date toDate = LocalDate.parse("2020-03-13").toDate();
BasicDBObject match = new BasicDBObject("$match",
new BasicDBObject("created",
new BasicDBObject("$gte", fromDate/*getDate("01/10/2019")*/).append("$lt", toDate/*getDate("20/10/2019")*/)));
BasicDBObject group = new BasicDBObject("$group",
new BasicDBObject ("_id",
new BsonField("averageTime",
new BsonDocument("$avg,",
new BsonString("$details.nostradamusOfferCalculatingTime")))));
List<Bson> aggregators = null;
assert false;
aggregators.add(match);
aggregators.add(group);
AggregateIterable<Document> output = dbCollection.aggregate(aggregators);
//AggregationOutput output1 = dbCollection.aggregate(Arrays.asList(match,group));
Document result = output.first();
return result.getDouble("averageTime");
}
But this jaja query is returning empty results (in line with: aggregators.add(match); - I get NullPointerException).
Mongo don't understand 01/10/2019 format rather it understand ISO format. Hence, you must be using something like ISODate("2015-06-17T10:03:46Z") in place of fromDate and toDate. Date or LocalDate don't work.

MongoDB date range query throws syntax errors when used in aggregation

I am using Java Driver for MongoDB to query database. I am getting syntax errors when trying to execute range query on a date field in aggregation. It works fine if I use it as part of find query only. Aggregation is the problem here. I used the following Java query code :
new BasicDBObject("requestDate", BasicDBObjectBuilder.start("$gte", fromDate).add("$lte", toDate).get());
requestDate is the field I want to query. I tried debugging the code and ran the generated query using command line and I still get syntax errors. Not sure whats wrong here.
Mongo Query generated by the code:
{ "requestDate" : { "$gte" : { "$date" : "2015-03-01T05:00:00.000Z"} , "$lte" : { "$date" : "2015-03-09T04:00:00.000Z"}}}
EDIT. Adding relevant Code:
BasicDBObject match = null;
if (organizationId != null) {
match = new BasicDBObject("$match", new BasicDBObject("organizationId", organizationId));
}
if (optionalParams != null) {
Date fromDate = (Date) optionalParams.get("fromDate");
Date toDate = (Date) optionalParams.get("toDate");
if (match == null) {
match = new BasicDBObject("requestDate", new BasicDBObject("$gte", fromDate).append("$lte", toDate));
} else {
match.append("requestDate", new BasicDBObject("$gte", fromDate).append("$lte", toDate));
}
}
DBObject project = new BasicDBObject("$project", MongoDBUtil.getProjectDateFields());
DBObject groupFields = new BasicDBObject("_id", MongoDBUtil.getGroupDateFields()).append("total", new BasicDBObject("$sum", 1));
DBObject group = new BasicDBObject("$group", groupFields);
DBObject sort = new BasicDBObject("$sort", new BasicDBObject("_id", 1));
List<DBObject> pipeline;
if (match != null) {
pipeline = Arrays.asList(match, project, group, sort);
} else {
pipeline = Arrays.asList(project, group, sort);
}
In brief, you broke your $match pipeline stage construction because like all pipeline directives that "key" is "mandatory. Your conditional building should not be checking is the existing state is null but rather "appending" to what you need to define at the top as a "empty" $match:
// BasicDBObject match = null; // wrong!
BasicDBObject match = new BasicDBObject("$match", new BasicDBObject()); // correct!
if (organizationId != null) {
match.append("organizationId", organizationId);
}
if (optionalParams != null) {
Date fromDate = (Date) optionalParams.get("fromDate");
Date toDate = (Date) optionalParams.get("toDate");
match.append("requestDate", new BasicDBObject("$gte", fromDate)
.append("$lte", toDate));
}
So then, without a value for organizationId you get a pipeline generated like so:
{ "$match": {
"requestDate" : {
"$gte" : { "$date" : "2015-03-01T05:00:00.000Z" },
"$lte" : { "$date" : "2015-03-09T04:00:00.000Z" }
}
}
Without that $match key this is not a valid pipeline stage and it will error on submission to the aggregation pipeline.
There is nothing wrong with the generated syntax and all, full explanation is in the manual under Extended JSON. The MongoShell uses "strict" mode as mentioned there so it requires it's own wrappers.

How to use aggregation in Mongo db Java driver with $match and $in?

How to convert below query into Java code for Mongo Java driver?
db.post.aggregate(
[
{ $match : {"name" :{'$in': ["michael", "jordan"] } }},
{ $group : { _id : "$game.id" , count : { $sum : 1 } } }
]
)
My function is not working:
DBObject match = new BasicDBObject('$match', new BasicDBObject("name", names));
The $in operator takes and array or list of arguments, so any list will basically do. But you need to form the corresponding BSON. Indenting your code helps to visualize:
BasicDBList inArgs = new BasicDBList();
inArgs.add("michael");
inArgs.add("jordan");
DBObject match = new BasicDBObject("$match",
new BasicDBObject("name",
new BasicDBObject("$in", inArgs )
)
);
DBObject group = new BasicDBObject("$group",
new BasicDBObject("_id","$game.id").append(
"count", new BasicDBObject("$sum",1)
)
);
According to the Aggregation Documentation, your query should look like:
DBObject match = new BasicDBObject('$match', new BasicDBObject('name', new BasicDBObject('$in', names)));

How to perform match on sum of two fields

I have a query in MySQL that contains the following condition:
WHERE START_TIME < ? AND START_TIME+DURATION >= ?
How should I migrate this to MongoDB using Java driver and aggregation framework?
The first condition will become:
DBObject match = new BasicDBObject("$match", new BasicDBObject("start_time", "{ $lt : "+timestamp+"}") );
But I'm not sure about the second.
Thanks.
EDIT
I've tried to work with Asya Kamsky answer, this is what I got but it's not working:
BasicDBList dbList = new BasicDBList();
dbList.add("$start_time");
dbList.add("$duration");
DBObject matchLT = new BasicDBObject("$match", new BasicDBObject("start_time", new BasicDBObject("$lt",timestamp)));
DBObject project = new BasicDBObject("$project", new BasicDBObject("end_time", new BasicDBObject("$add", dbList)));
DBObject matchGTE = new BasicDBObject("$match", new BasicDBObject("end_time", new BasicDBObject("$gte",timestamp)));
//GROUP CODE GOES HERE
AggregationOutput output = collection.aggregate(matchLT, project, matchGTE, group);
Here's how you do it in Aggregation Framework, I'm sure you can translate this to Java:
db.collection.aggregate([ {$match: {start_time:{$lt:ISODate("xxxx-xx-xx")}}},
{$project:{end_time:{$add:["$start_time","$duration"]}}},
{$match:{end_time:{$gt:ISODate("yyyy-yy-yy")}}}
] );

(MongoDB Java) $push into array

I'm using mongo 2.2.3 and the java driver.
My dilemma, I have to $push a field and value into an array, but I cant seem to figure out how to do this. A sample of my data:
"_id" : 1,
"scores" : [
{
"type" : "homework",
"score" : 78.97979
},
{
"type" : "homework",
"score" : 6.99
},
{
"type" : "quiz",
"score" : 99
}
]
I can $push in the shell:
db.collection.update({_id:1},{$push:{scores:{type:"quiz", score:99}}})
but it's when I translate this into java I confuse my self and chuck my keyboard at a wall.
my java code (incomplete and wrong) so far:
DBObject find = new BasicDBObject("_id", 1);
DBObject push = new BasicDBObject("$push", new BasicDBObject(
"scores", new BasicDBObject()));
DBObject listItem = new BasicDBObject("scores", new BasicDBObject("type","quiz").append("score",99));
DBObject updateQuery = new BasicDBObject("$push", listItem);
myCol.update(findQuery, updateQuery);
Since mongodb-driver 3.1. there is a builder class com.mongodb.client.model.Updates with appropriate methods for each update case. In this case this would be:
Document score = new Document().append("type", "quiz")
.append("score",99);
collection.updateOne(eq("_id", "1"),Updates.addToSet("scores", score));
If you're more comforable with the query format of the shell, you may find it's easier to use JSON.parse to contstruct your DBObject for the $push:
import com.mongodb.util.JSON;
String json = "{$push:{scores:{type:'quiz', score:99}}}";
DBObject push = (DBObject) JSON.parse(json);
Using Jongo, you can do as in the shell:
db.collection.update({_id:1},{$push:{scores:{type:"quiz", score:99}}})
Becomes in Java:
collection.update("{_id:1}").with("{$push:{scores:{type:#, score:#}}}", "quiz", 99);
No fancy DBObject needed ;-)
MongoDB Java driver can simplify this. Use $each instead of $push.
$each mongodb reference document
Java sample -
BasicDBObject addressSpec = new BasicDBObject();
addressSpec.put("id", new ObjectId().toString());
addressSpec.put("name", "one");
BasicDBObject addressSpec2 = new BasicDBObject();
addressSpec2.put("id", new ObjectId().toString());
addressSpec2.put("name", "two");
List<BasicDBObject> list = new ArrayList<>();
list.add(addressSpec); list.add(addressSpec2);
UpdateResult updateOne = individualCollection.updateOne(Filters.eq("_id", "5b7c6b612612242a6d34ebb6"),
Updates.pushEach("subCategories", list));

Categories

Resources