implementing mongodb query in java using java mongo driver - java

I am using the below mongo query to get the max temperature. Can any one help how to implement in java using mongo java driver using BasicDBObject and DBObject?
db.EventLog.aggregate(
[
{
$group:
{
_id: "$_id",
maxInnerTemp: { $max: { $concat : [ "0", "$fields.innerTemp"]}}
}
}
]
)

Use mongo java aggregation like below code ( not tested ) :
// $group operation
BasicDBList concat = new BasicDBList();
concat.add("0");
concat.add("$fields.innerTemp");
DBObject groupFields = new BasicDBObject("_id", "$_id");
groupFields.put("maxInnerTemp", new BasicDBObject("$max", new BasicDBObject("$concat", concat));
DBObject group = new BasicDBObject("$group", groupFields);
// run aggregation
List < DBObject > pipeline = Arrays.asList(group); AggregationOutput output = collectionName.aggregate(pipeline);
for (DBObject result: output.results()) {
System.out.println(result);
}

Related

Translating "value in array column" MongoDB query to MongoDB Spring Data code

How can I translate the following MongoDB query into Java-based query using the Java MongoDB Spring Data driver?
db.User.aggregate([
{ $match : { $expr: { $in: [ "ADMIN", "$roles" ] } } },
{ $sort : { "createdAt": 1 } },
{ $limit : 1 }
])
My attempted solution in Kotlin, which I think is wrong (I don't know how to specify that "roles" is a field in the User document).
fun queryFirstAdmin(): User? {
val matchRolesOpt = Aggregation.match(Criteria.where("ADMIN").`in`("roles"))
val sortOpt = Aggregation.sort(Sort.Direction.ASC, "createdAt")
val limitOpt = Aggregation.limit(1)
var ops: MutableList<AggregationOperation> = mutableListOf()
ops.add(matchRolesOpt)
ops.add(sortOpt)
ops.add(limitOpt)
var aggregation = Aggregation.newAggregation(*ops.toTypedArray())
val aggregationResult = mongoTemplate.aggregate(aggregation, User::class.java, User::class.java)
return aggregationResult.uniqueMappedResult
}
This solution works but unfortunately it returns a slice of the User document (since it has been unwound):
fun queryFirstAdmin(): User? {
val unwindOpt = Aggregation.unwind("roles")
val matchRolesOpt = Aggregation.match(Criteria.where("roles").`is`("ADMIN"))
val sortOpt = Aggregation.sort(Sort.Direction.ASC, "createdAt")
val limitOpt = Aggregation.limit(1)
var ops: MutableList<AggregationOperation> = mutableListOf(unwindOpt, matchRolesOpt, sortOpt, limitOpt)
var aggregation = Aggregation.newAggregation(*ops.toTypedArray())
val aggregationResult = mongoTemplate.aggregate(aggregation, User::class.java, User::class.java)
return aggregationResult.uniqueMappedResult
}
i.e. if the Document returned has the array ["ADMIN"] but the original document has ["ADMIN","USER] in the "roles" field
How can I fix this?
The MongoDB Spring Data Java code for the aggregation:
MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "test");
Aggregation agg = newAggregation(
match(where("roles").is("ADMIN")),
sort(ASC, "createdAt"),
limit(1L)
);
AggregationResults<Document> results = mongoOps.aggregate(agg, "User", Document.class);
results.forEach(System.out::println);
NOTE:
The match stage in the aggregation
{ $match : { $expr: { $in: [ "ADMIN", "$roles" ] } } }
can be replaced with this and the result is the same:
{ $match : { roles: "ADMIN" } }
The same query using MongoDB Java Driver:
Bson match = match(expr( Document.parse(" { $in: [ 'ADMIN', '$roles' ] } ")));
// -or-
// Bson match = match(eq("roles", "ADMIN"));
List<Bson> pipeline =
Arrays.asList(match, sort(ascending("createdAt")), limit(1));
List<Document> results = new ArrayList<>();
collection.aggregate(pipeline).into(results);
results.forEach(System.out::println);

Converting Mongo aggregate query into java objects

I am trying to convert a mongo aggregate query into java objects. When I am running the query in RoboMongo (tool), I get the result but converting into java objects gives empty results.
Mongo Query:
db.getCollection('wb_physicians').aggregate([
{
$match: {
$and: [
{ "product.mpoCode": "VA001"},
{ "product.npoCode": { $exists: true } }
]
}
},
{
"$project" : {
"product.specialties.code": 1,
"providerId": 1,
"product.code": 1,
"_id" : 0
}
},
{ "$unwind" : "$product.specialties" },
{
"$group" : {
"_id" : {
"providerId": "$providerId" ,
"productCode": "$product.code"
},
"specialityCodeList": { "$addToSet": "$product.specialties.code" }
}
}
])
Java Code:
private static AggregationOutput findProviderandSpecialty(DBCollection collection) {
DBObject match = new BasicDBObject("$match" ,
new BasicDBObject("$and", Arrays.asList(
new BasicDBObject("product.mpoCode" , "VA001").append("product.npoCode", "$exists: true")
))
);
DBObject project = new BasicDBObject("$project" ,
new BasicDBObject("product.specialties.code" , 1)
.append("providerId" , 1)
.append("product.code", 1)
.append("_id", 0)
);
DBObject unwind = new BasicDBObject("$unwind" , "$product.specialties");
DBObject group = new BasicDBObject("$group",
new BasicDBObject("_id", new BasicDBObject("providerId" , "$providerId"))
.append("specialityCodeList",
new BasicDBObject("$addToSet", "$product.specialties.code")
)
);
AggregationOutput output = collection.aggregate(match,project,unwind,group);
return output;
}
Could you please help me where I made the wrong mapping?
The problem is on the $match pipeline:
DBObject match = new BasicDBObject("$match" ,
new BasicDBObject("$and", Arrays.asList(
new BasicDBObject("product.mpoCode" , "VA001")
.append("product.npoCode", "$exists: true")
))
);
should be
DBObject match = new BasicDBObject("$match" ,
new BasicDBObject("$and", Arrays.asList(
new BasicDBObject("product.mpoCode" , "VA001"),
new BasicDBObject("product.npoCode",
new BasicDBObject("$exists", "true")
)
))
);
Nonetheless, you can do without the explicit $and logic by specifying a comma-separated expression of the documents as well as removing the $project pipeline before the $group
as it's rather unnecessary, so your revised pipeline could be run as:
db.getCollection('wb_physicians').aggregate([
{
"$match": {
"product.mpoCode": "VA001",
"product.npoCode": { "$exists": true }
}
},
{ "$unwind" : "$product.specialties" },
{
"$group" : {
"_id" : {
"providerId": "$providerId" ,
"productCode": "$product.code"
},
"specialityCodeList": { "$addToSet": "$product.specialties.code" }
}
}
])
And the final Java code:
private static AggregationOutput findProviderandSpecialty(DBCollection collection) {
DBObject match = new BasicDBObject("$match" ,
new BasicDBObject("product.mpoCode" , "VA001").append("product.npoCode",
new BasicDBObject("$exists", "true")
)
);
DBObject unwind = new BasicDBObject("$unwind" , "$product.specialties");
DBObject group = new BasicDBObject("$group",
new BasicDBObject("_id", new BasicDBObject("providerId" , "$providerId"))
.append("specialityCodeList",
new BasicDBObject("$addToSet", "$product.specialties.code")
)
);
List<DBObject> pipeline = Arrays.<DBObject>asList(match, unwind, group);
AggregationOutput output = collection.aggregate(pipeline);
return output;
}

Creating Spring Data Aggregation of multiple MongoDB queries

The database MongoDB I have stored documents in the format:
{
"achievement": [
{
"userFromId":"max",
"userToId":"peter",
"date":"2016-01-25",
"pointCount":1,
"description":"good work",
"type":"THANKS"
}
]
}
How to get the number of records in the database (if any) for the a certain date, in which people are thanking the other people.
I created a query to retrieve data:
DBObject clause1 = new BasicDBObject("userFromId", userFromId);
DBObject clause2 = new BasicDBObject("userToId", userToId);
DBObject clause3 = new BasicDBObject("sendDate", localDate);
DBObject clause4 = new BasicDBObject("type", Thanks);
BasicDBList or = new BasicDBList();
or.add(clause1);
or.add(clause2);
or.add(clause3);
or.add(clause4);
DBObject query = new BasicDBObject("$or", or);
But I do not know how to get the number of records and how can rewrite the query using aggregation?
For example:
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.group("userFromId")
.first("userFromId").as("userFromId")
.sum("pointCount").as("pointCount"));
I do not know how to add a few more parameters.
What the return request if the data to the database does not exist?
Thanks for any help
You can use something like this. This will count all the number of documents matching the below criteria.
Regular Query
db.collection.count({ $or: [ { "userFromId": userFromId }, { "userToId": userToId } ] });
Using Aggregation
db.collection.aggregate( [
{ $match: { $or: [ { "userFromId": userFromId }, { "userToId": userToId } ] } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );

New aggregation feature with Mongo 3.2 driver, using Java

I want to perform an aggregation in Mongo 3.2 as explained here, but in Java:
https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup
At the moment my query object in java is very simple:
Document query = new Document();
query.append("employeId", employeId);
In addition to filtering by employeId, I would like to join this collection with company (where employee.company_id = company.id)
How can I do that in Java? It seems like I cannot find documentation of this new Mongo feature.
EDIT
Example of Employee collection:
{
"id" : 1,
"name" : "John",
"lastName" : "Moore",
"age" : 44,
"companyId": 10
}
Example of Company collection:
{
"id" : 10,
"companyName" : "Microsoft",
"numEmployee" : 100
}
Example of output expected
{
"id" : 1,
"name" : "John",
"lastName" : "Moore",
"companyId" : 10,
"companyName" : "Microsoft"
}
Running the following aggregation pipeline should give you the needed result
pipeline = [
{
"$match": {
"_id": employeeId
}
},
{
"$lookup": {
"from": "company",
"localField": "companyId",
"foreignField": "_id",
"as": "company"
}
},
{
"$project": {
"name": 1,
"lastName": 1,
"companyId": 1,
"companyName": "$company.companyName"
}
}
];
db.employee.aggregate(pipeline);
Java test implementation
public class JavaAggregation {
public static void main(String args[]) throws UnknownHostException {
MongoClient mongo = new MongoClient();
DB db = mongo.getDB("test");
DBCollection coll = db.getCollection("employee");
// create the pipeline operations, first with the $match
DBObject match = new BasicDBObject("$match",
new BasicDBObject("_id", employeeId)
);
// build the $lookup operations
DBObject lookupFields = new BasicDBObject("from", "company");
lookupFields.put("localField", "companyId");
lookupFields.put("foreignField", "_id");
lookupFields.put("as", "company");
DBObject lookup = new BasicDBObject("$lookup", lookupFields);
// build the $project operations
DBObject projectFields = new BasicDBObject("name", 1);
projectFields.put("lastName", 1);
projectFields.put("companyId", 1);
projectFields.put("companyName", "$company.companyName");
DBObject project = new BasicDBObject("$project", projectFields);
List<DBObject> pipeline = Arrays.asList(match, lookup, project);
AggregationOutput output = coll.aggregate(pipeline);
for (DBObject result : output.results()) {
System.out.println(result);
}
}
}

Convert mongoDB shell command to java

I am trying to convert the mongodb shell code below to java. However, i run into some problems doing so. Can anyone help me with this issue?
MongoDB
var friend_ids = db.users.findOne(ObjectId("...")).friend_ids
db.users.find({_id:{$in:friend_ids}})
Java
ObjectId id = new ObjectId("...");
BasicDBObject fields = new BasicDBObject("friend_ids", 1).append("_id", false);
DBObject f_ids = coll.findOne(id, fields);
BasicDBObject query = new BasicDBObject("_id",(new BasicDBObject("$in", f_ids)));
DBCursor cursor = coll.find(query);
The java query is as follows.
query={ "_id" : { "$in" : { "friend_ids" : [ { "$oid" : "..."} , { "$oid" : "..."} , { "$oid" : "..."}]}}},
thanks
You need extract friend_ids from f_ids.
BasicDBObject query = new BasicDBObject("_id",(new BasicDBObject("$in", f_ids.get("friend_ids"))));

Categories

Resources