MongoDb Java Driver v3.x and aggregation framework - java

I have a collection containing contacts and each contact document has a firstName and lastName attribute.
Now I want to query the database by using Java and the MongoDb Java driver in version 3.2.
I try to find a contact with a concatenated firstName + lastName. My query looks like the following for the MongoDb shell:
db.getCollection('contacts').aggregate(
{
$project:{
fullName:{
$concat: [ "$firstName", " ", "$lastName" ]
}
}
},
{
$match:{
fullName:"John Doe"
}
}
);
Now I tried to get my head around the MongoDb Java driver to get the same accomplished in Java:
AggregateIterable<Document> documents = contactUserCollection.aggregate(Arrays.asList(project(computed("fullName", "$firstName $lastName")), match(eq("fullName", firstLastName))));
But this isn't working.
Does someone have an idea how I could accomplish this?
Thank you

You could try the following:
/*
MONGO SHELL :
var pipeline = [
{
"$project": {
"otherfieldsA": 1,
"otherfieldsB": 1,
"otherfieldsC": 1,
"fullName": {
"$concat": [ "$fistName", " ", "$lastName" ]
}
}
}
{
"$match": { "fullName": "John Doe" }
}
];
db.contacts.aggregate(pipeline);
*/
public class JavaAggregation {
public static void main(String args[]) throws UnknownHostException {
MongoClient mongo = new MongoClient();
DB db = mongo.getDB("test");
DBCollection coll = db.getCollection("contacts");
// create the pipeline operations, build the $project operations
BasicDBList concatenate = new BasicDBList();
concatenate.add("$firstName");
concatenate.add(" ");
concatenate.add("$lastName");
DBObject fullName = new BasicDBObject("$concat", concatenate);
DBObject fields = new BasicDBObject("otherfieldsA", 1);
fields.put("otherfieldsB", 1);
fields.put("otherfieldsC", 1);
fields.put("fullName", fullName);
DBObject project = new BasicDBObject("$project", fields);
// create the $match operator
DBObject match = new BasicDBObject("$match",
new BasicDBObject("fullName", "John Doe")
);
AggregationOutput documents = coll.aggregate(match, project, group, sort);
for (DBObject result : documents.results()) {
System.out.println(result);
}
}
}

Related

How to fetch the particular data from Mongo subdocument in java?

I have tried to fetch data for the particular column value in the mongo document but its displaying whole data.
Following is the mongo document:
{
"_id" : ObjectId("59db2321811a592384865711"),
"User_ID" : "demo",
"Project_ID" : "demo-1",
"Project_Information" : {
"Project_Description" : "Sample",
"Primary_Building_Type" : "Office",
"State" : "AR",
"Analysis_Type" : "1",
"Project_Billing_Number" : "WY",
"Country" : "USA",
"Climate_Zone" : "3A",
"Zip_Code" : "71611"
"City" : "WA",
"Units" : "IP"
}
}
I want to fetch the following output:
[
{
"User_ID": "demo",
"Project_Description": "Sample"
}]
I have tried using dot: Project_Information.Project_Description.The code is as below:
public Object[] addDemo1(String User_ID) throws Exception {
DB db = ConnectToDB.getConnection();
Properties prop = new Properties();
InputStream input = null;
input = GetProjectStatus.class.getClassLoader().getResourceAsStream("config.properties");
prop.load(input);
String col = prop.getProperty("COLLECTION_PI");
System.out.println("data is.." + col);
DBCollection collection = db.getCollection(col);
BasicDBObject obj = new BasicDBObject();
BasicDBObject fields = new BasicDBObject();
BasicDBObject fields2 = new BasicDBObject();
List<DBObject> obj1 = null;
if (User_ID != null && !User_ID.equals("") && User_ID.length() > 0) {
obj.put("User_ID", User_ID);
fields.put("_id", 0);
fields.put("User_ID", 1);
fields.put("Project_ID", 1);
fields.append("Project_Information.Project_Description", "Project_Description");
BasicDBObject fields1 = new BasicDBObject();
fields1.put("User_ID", User_ID);
}
DBCursor cursor = collection.find(obj, fields);
System.out.println("count is:" + cursor.count());
obj1 = cursor.toArray();
System.out.println("" + obj1);
cursor.close();
db.getMongo().close();
return obj1.toArray();
}
But it displays the whole structure of Project_Information.
Please specify how to achieve this. Thanks for help.
Using a 2.x MongoDB Java Driver
Here's an example using the MongoDB 2.x Java driver:
DBCollection collection = mongoClient.getDB("stackoverflow").getCollection("demo");
BasicDBObject filter = new BasicDBObject();
BasicDBObject projection = new BasicDBObject();
// project on "Project_Information.Project_Description"
projection.put("Project_Information.Project_Description", 1);
DBCursor documents = collection.find(filter, projection);
for (DBObject document : documents) {
// the response contains a sub document under the key: "Project_Information"
DBObject projectInformation = (DBObject) document.get("Project_Information");
// the "Project_Description" is in this sub document
String projectDescription = (String) projectInformation.get("Project_Description");
// prints "Sample"
System.out.println(projectDescription);
// to return this single String value in an Object[] (as implied by your OP) just do create the Object[] like this and then return it ...
Object[] r = new Object[] {projectDescription};
// prints the entire projected document e.g.
// { "_id" : { "$oid" : "59db2321811a592384865711" }, "Project_Information" : { "Project_Description" : "Sample" } }
System.out.println(document.toString());
}
Using a 3.x MongoDB Java Driver
Here's an example using the MongoDB 3.x Java driver:
// this finds all documents in a given collection (note: no parameter supplied to the find() call)
// and for each document it projects on Project_Information.Project_Description
FindIterable<Document> documents =
mongoClient.getDatabase("...").getCollection("...")
.find()
// for each attrbute you want to project you must include its dot notation path and the value 1 ...
// this is the equivalent of specifying {'Project_Information.Project_Description': 1} in the MongoDB shell
.projection(new Document("Project_Information.Project_Description", 1));
for (Document document : documents) {
// the response contains a sub document under the key: "Project_Information"
Document projectInformation = (Document) document.get("Project_Information");
// the "Project_Description" is in this sub document
String projectDescription = projectInformation.getString("Project_Description");
// prints "Sample"
System.out.println(projectDescription);
// to return this single String value in an Object[] (as implied by your OP) just do create the Object[] like this and then return it ...
Object[] r = new Object[] {projectDescription};
// prints the entire projected document e.g. { "_id" : { "$oid" : "59db2321811a592384865711" }, "Project_Information" : { "Project_Description" : "Sample" } }
System.out.println(document.toJson());
}
Java libraries won't let you directly access using dot.
They have build in getter and setter methods.
You have not mentioned which package you are using.
Here's the query that you need:
db.mycol.find({},{User_ID:1,"Project_Information.Project_Description":1})
It will give:
{ "_id" : ObjectId("59db2321811a592384865711"),
"User_ID" : "demo",
"Project_Information" : { "Project_Description" : "Sample" }
}
You will have to convert the query in whatever format your package accepts.
Here's a tutorial:
https://www.mongodb.com/blog/post/getting-started-with-mongodb-and-java-part-i

Mongo Query with $in array in Java

I am trying to create this query from Java for MongoDB.
Do you know how can I construct it in java?
db.node.find({
connectedWithIds: { $in: [
ObjectId('56bca32fe74a987ad8724da1')
] }
})
I tried to use this:
ObjectId arr[] = {new ObjectId("5409ae2e2cdc31c5aa0ce0a5")};
BasicDBObject inQuery = new BasicDBObject("$in", arr);
BasicDBObject query = new BasicDBObject("connectedWithIds", inQuery);
but the results is below:
{ "connectedWithIds" : { "$in" : [ { "$oid" : "5409ae2e2cdc31c5aa0ce0a5"}]}}
and occurs this error:
error: {
"$err" : "Can't canonicalize query: BadValue cannot nest $ under $in",
"code" : 17287
}
I could overcome this error with the code below:
ArrayList<ObjectId> vals = new ArrayList<ObjectId>();
vals.add(objectId);
BasicDBObject inQuery = new BasicDBObject("$in", vals);
BasicDBObject query = new BasicDBObject("connectedWithIds", inQuery);
List<BasicDBObject> users = (List<BasicDBObject>) customQueryManager.executeQuery("node", query);

Auto increment sequence in mongodb using java

Hi I want to auto increment _id in mongodb using java. I am completely new to this. In the document I found the solution like this:
db.counters.insert(
{
_id: "userid",
seq: 0
}
)
function getNextSequence(name) {
var ret = db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
db.users.insert(
{
_id: getNextSequence("userid"),
name: "Sarah C."
}
)
Can any one suggest how do I do this using java ? I am completely new to this.
Using Create an Auto-Incrementing Sequence Field first you should create collection using mongoDB shell and collection should be as :
db.counters.insert(
{
_id: "userid",
seq: 0
})
So you get counters collections which contains field like _id,seq, now create getNextSequence function in java and this function having parameter userid as string so getNextSequence function like this :
public static Object getNextSequence(String name) throws Exception{
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// Now connect to your databases
DB db = mongoClient.getDB("demo");
DBCollection collection = db.getCollection("counters");
BasicDBObject find = new BasicDBObject();
find.put("_id", name);
BasicDBObject update = new BasicDBObject();
update.put("$inc", new BasicDBObject("seq", 1));
DBObject obj = collection.findAndModify(find, update);
return obj.get("seq");
}
The above function return seq count and used this function in main method as like :
public static void main(String[] args) throws Exception {
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// Now connect to your databases
DB db = mongoClient.getDB("demo");
DBCollection collection = db.getCollection("counters");
BasicDBObject document = new BasicDBObject();
document.put("_id", getNextSequence("userid"));
document.put("name","Sarah C.");
collection.insert(document); // insert first doc
document.put("_id", getNextSequence("userid"));
document.put("name", "Bob D.");
collection.insert(document); // insert second doc
}
Now in counters collection contains three documents which contains name as Sarah C. and Bob D. respectively and one default documents which we inserted manually at first time and it increment seq like this { "_id" : "userid", "seq" : 2 }
DBCollection collection = database.getCollection("Table Name");
DBObject modifier = new BasicDBObject("counter", 1);
DBObject incQuery = new BasicDBObject("$id", modifier);

Return random elements nested in mongo document

I has the following json document in Mongo db. The show element will have several season elements which will also have several episodes elements that in turn have multiple questionEntry elements.
{
"show":[
{
"season":[
{
"episodes":[
{
"questionEntry":{
"id":1,
"info":{
"seasonNumber":1,
"episodeNumber":5,
"episodeName":"A Hero Sits Next Door"
},
"questionItem":{
"theQuestion":"What is the name of the ringer hired by Mr. Weed?",
"attachedElement":{
"type":1,
"value":""
}
},
"options":[
{
"type":1,
"value":"Johnson"
},
{
"type":1,
"value":"Hideo"
},
{
"type":1,
"value":"Guillermo"
}
],
"answer":{
"questionId":1,
"answer":3
},
"metaTags":[
"Season 1",
"Episode 5",
"Trivia",
"Arya Stark",
"House Stark"
]
}
}
]
}
]
}
]
}
I have been able to return questionElement(s) where the questionElements metaTag entry equals my search. E.G. if a metaTag element equals my string then return the questionEntry element that the metaTag element resides in and search the whole show element and return all that match using this code:
(thanks to Yathish Manjunath for help with this piece of code)
private DB mongoDatabase;
private DBCollection mongoColl;
private DBObject dbObject;
// Singleton class
// Create client (server address(host,port), credential, options)
mongoClient = new MongoClient(new ServerAddress(host, port),
Collections.singletonList(credential),
options);
mongoDatabase = ClientSingleton.getInstance().getClient().getDB("MyDB");
queryMetaTags("Season 1");
//#SuppressWarnings("deprecation")
public void queryMetaTags(String query)
{
List<String> continentList = Arrays.asList(new String[]{query});
DBObject matchFields = new
BasicDBObject("show.season.questions.questionEntry.metaTags",
new BasicDBObject("$in", continentList));
DBObject groupFields = new BasicDBObject( "_id",
"$_id").append("questions",
new BasicDBObject("$push","$show.season.questions"));
//System.out.println("2");
DBObject unwindshow = new BasicDBObject("$unwind","$show");
DBObject unwindsea = new BasicDBObject("$unwind", "$show.season");
DBObject unwindepi = new BasicDBObject("$unwind",
"$show.season.questions");
DBObject match = new BasicDBObject("$match", matchFields);
DBObject group = new BasicDBObject("$group", groupFields);
#SuppressWarnings("deprecation")
AggregationOutput output =
mongoColl.aggregate(unwindshow,unwindsea,unwindepi,match,group);
String s = JSON.serialize(dbObject);
JSONObject json = null;
for (DBObject result : output.results())
{
System.out.println(result);
// pretty view for testing
try
{
json = new JSONObject(result);
System.out.println(json.toString(4));
}
catch (JSONException e1)
{
e1.printStackTrace();
}
}
System.out.println("In end of queryMetaTags");
}
I want to search like above but only return 10 random matching questionEntry elements? What is the best and most efficient way to achieve this?
I have to say I'm totally new to search queries for any database and just can't figure out how to achieve a slick solution? Hopefully somebody here can help with this.
You can use the $limit in the aggregation chain. Note that you have to add it as the last chain.
{ $limit: <positive integer> }
So in your case,
{ $limit: 10 }

delete an specific embedded object in mongodb

Here is my java program:
try {
MongoClient mongoClient = null;
mongoClient = new MongoClient( "localhost" , 27017);
DB db = mongoClient.getDB("SchoolProject");
boolean auth = db.authenticate("root", "root#123".toCharArray());
System.out.println(auth);
if(auth==true){
DBCollection table = db.getCollection("Bus_route");
BasicDBObject query = new BasicDBObject();
query.put("BusId", "BUS_101");
BasicDBObject data = new BasicDBObject();
data.put("Route.$.stop_name", "hyderabad");
data.put("Route.$.arrival_time", "1:05");
BasicDBObject command = new BasicDBObject();
command.put("$unset", data);
table.update(query, command);
}
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
and mongodb document:
"BusId" : "BUS_101",
"DriverName" : "Alex",
"Route" : [
{
"stop_name" : "st. John Road",
"arrival_time" : "10:30"
},
{
"stop_name" : "hyderabad",
"arrival_time" : "1:05"
}
],
"SchoolName" : "St. John Paul",
"VehicleNo" : "A20y6757",
"_id" : ObjectId("529f093cdaa62b1b10b82cc1")
and
document name: Bus_route
delete an specific embedded object in mongodb
how to delete object named hyderabad in an array Route with out removing others?
after I got help from this forum I got it, below is the code
DBCollection table = db.getCollection("Bus_route");
BasicDBObject query = new BasicDBObject();
query.put("BusId", "BUS_101");
BasicDBObject data = new BasicDBObject();
data.put("stop_name", "hyderabad");
BasicDBObject command = new BasicDBObject();
command.put("$pull", new BasicDBObject("Route", data));
table.update(query, command);

Categories