MongoDB querying with Java API - java

Here is the sample document of my MongoDB:
user:{
_id:1,
name:'xyz',
age:12,
mobile:21321312,
transaction:[{
trans_id:1,
prod:'a',
purchasedAt:ISODate("2015-02-01"),
},
{
trans_id:2,
prod:'b',
purchasedAt:ISODate("2015-02-01")
},
{
trans_id:3,
prod:'c',
purchasedAt:ISODate("2014-11-24")
}]
,...
}
My query looks like:
db.user.find({transaction:{$elemMatch:{prod:'a', purchasedAt:ISODate("2015-02-01")}}, transaction:{$elemMatch:{prod:{$nin:['b','c']}, purchasedAt:ISODate("2015-02-01")}}}).count()
I am trying to get the user count who have purchased product 'a' on date "2015-02-01" but not have purchased product b & c on same day.
So while trying to do this in Java with the query:
coll.find(new BasicDBObject().append("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", 'a').append("purchasedAt", Date))).append("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", new BasicDBObject("$nin",['b','c'])).append("purchasedAt", Date)));
I have also tried:
coll.find(new BasicDBObject("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", 'a').append("purchasedAt", Date))).append("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", new BasicDBObject("$nin",['b','c'])).append("purchasedAt", Date)));
where Date is "2015-02-01" in util.Date object.
I found out that Java ignores the $in part of the query, i.e. it ignores {transaction:{$elemMatch:{prod:'a', purchasedAt:ISODate("2015-02-01")}} & performs only $nin part.
I found out it by DBCursor object.
Here's the output of the cursor:
Cursor: Cursor id=0, ns=mydb.user, query={ "transaction" : { "$elemMatch" : { "prod" : { "$nin" : [ "b" , "c"]} , "purchasedAt" : { "$date" : "2015-02-01T00:00:00.000Z"}}}}, numIterated=0, readPreference=primary
Because of this my result is inaccurate. I wonder why the exact same query works well in Mongo shell but doesn't with Java API. Is there anything wrong with my query structure?

My guess is that this question is now moot, but, if you still do not consider it answered, are you looking for the "$not" operator, which can check for non-existance sort of.

Related

Unable to find a document in Mongodb where exact date match in java

Statement: I am trying to get the documents from MongoDB collection (Emp) using java.
Condition: Where it matches with the DOB(Date of birth) of a person.
Problem: However, it never returns a record.
But it works perfectly for other fields such as EmpID or EmpName etc. The document of my collection looks like this,
{
"_id" : ObjectId("5d4d9059f0b31921a4916a0c"),
"EmpID" : "1001",
"EmpName" : "John",
"Sal" : 30000.0,
"DOB" : ISODate("1989-06-09T18:30:00.000+0000"),
"Age" : 31.0
}
Please find the following java code that I have tried,
BasicDBObject dbo = new BasicDBObject();
dbo.append("DOB", new BasicDBObject("$eq","1989-06-10T00:00:00.000"));
FindIterable<Document> doc = coll.find(dbo);
for (Document dox : doc)
{
System.out.println(dox.toJson());
}
Please help
For ISODate it's needed to pass the Date object in BasicDBObject, not String, also timezone must be provided:
dbo.append("DOB", new BasicDBObject("$eq",new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXX").parse("1989-06-10T00:00:00.000+0000")));
For Date Of Birth better to use $gte and $lt comparition operators together in order to take full range of single day, like that:
Date dayStart = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXX").parse("1989-06-10T00:00:00.000+0000");
Date dayEnd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXX").parse("1989-06-11T00:00:00.000+0000");
BasicDBObject query = new BasicDBObject("Date", new BasicDBObject("$gt", dayStart).append("$lte", dayEnd));

Nested Querying in mongodb datase

I am bit new to mongodb and also in java. I want to query the key breaktime and find the sum of the value.
db.users90.find().pretty()
{
"_id" : ObjectId("5ad5f2e2f58a542f7989e8fc"),
"date" : "2018-04-17",
"break" : [
{
"out" : "18:00",
"in" : "18:40",
"breaktime" : "0:40"
},
{
"out" : "19:00",
"in" : "19:30",
"breaktime" : "0:30"
}
]
}
I need a help in java, to add those 2 breaktime keys(some cases it may be n number of documents in break)
0:40+0:30 = 0:70 minutes
Thanks,
Mohan
Although the query you need is simple, having your "breaktime" values stored as String, makes everything difficult and complex for no reason.
So, assuming you have stored these values as numbers e.g. double, you could easily execute your query in Java like this;
AggregateIterable aggregationQuery = collection.aggregate(Arrays.asList(
new Document("$match", new Document("date","yourDate")), // match a document with a specific date
new Document("$unwind", "$break"), // decompose the 'break' array
new Document("$group", new Document("_id", null).
append("totalBreakTime", new Document("$sum","$break.breaktime"))
)));
if (aggregationQuery.iterator().hasNext()){
double totalBreakTime = ((Document)aggregationQuery.iterator().next()).get("break",Document.class).getDouble("breakTime");
}

How to delete mongodb document with two conditions one with $gt operator?

I would like to retrieve the following information:
delete from database where name = 'AAA' and age>20;
but for MongoDB in Java. Essentially, it should delete the document that contain the word AAA and age greater than 20 in them. I know that there is the $in operator in MongoDB, but how do I do the same in Java, using the Java driver? I've been trying to look for it everywhere but am getting nothing. I've tried:
query = new BasicDBObject("age", new BasicDBObject("$gt", "20"), new BasicDBObject("name", "AAA"));
JSON which i want to delete is like this.
{"school" : "NewSchool" , "name" : "AAA" , "age" : "50"}
What you want is the find-term:
{
"name" : "AAA",
"age" : { $gt : 20 }
}
Construct this as your basic DB object, or simply use the new 3.x Filters to create the Bson for you. (As I personally only use 3.x, here's the appropriate example):
MongoClient client = ...
MongoDatabase db = client.getDatabase(...);
MongoCollection<Document> coll = db.getCollection(...);
coll.deleteMany(Filters.and(Filters.eq("name", "AAA"), Filters.gt("age", 20)));

MongoDB Date query JAVA

Im trying to do a query to get all the values from my DB wich each have a date. One example:
leadTime: [
{
date: ISODate("2014-03-19T23:00:00Z"),
value: 25.8
},
{
date: ISODate("2014-03-20T23:00:00Z"),
value: 31.299999999999997
},
{
date: ISODate("2014-03-21T23:00:00Z"),
value: 34.4
}
]
enter code here
My code is:
DBObject query=new BasicDBObject("group",group);
DBObject serieData= col.findOne(query,new BasicDBObject(serie, 1));
if (serieData != null) {
List<DBObject> data = (List<DBObject>) serieData.get(serie);
for (DBObject item : data) {
result.add(new HistoryData((Date) item.get("date"),(Double) item.get("value")));
}
Now I want to get the values that the date is bigger than a date that I pass by parameter. The query I did is this:
DBObject query=new BasicDBObject("group",group)
.append("date", new BasicDBObject("$gte", parameterDate))
;
But I always receive the result empty, can you help me? sorry for my english and than
Assuming that leadTime is a field in your documents, your query has to look like this
DBObject query=new BasicDBObject("group",group)
.append("leadTime.date", new BasicDBObject("$gte", parameterDate))
;
The way you did it, MongoDB would have searched for a date field in your document root:
{ _id: "Foo",
date: ISODate("2014-03-19T23:00:00Z"),
[...]
}
Queries in MongoDB don't make a difference if the queried field is a single value or an array, so using the dot notation on a field which holds an array of subdocuments is perfectly valid.
What you want to do is not possible with a simple query.
But if you still want to do it in mongodb you need to use the aggregation framework, with something like that :
db.<col_name>.aggregate( [ { $unwind : "$group" }, { $match : {'group.date': { $gte : parameterDate } } ] )
this a js command, but you should be able to translate it easly in Java Driver (you can also add a $project operation to just return needed fields).

How to access nested element of mongo query result using Java and R?

I am using Java and R to fetch data from my database and implement prediction. My json in mongodb is like:
{
"Server" : [
{
"deviceName" : "NEWSCVMM",
"availability" : 100,
"osVersion" : "6.3.9600",
"averageResponseTime" : 0.422,
"useswapmemory" : "983040",
"freeswapmemory" : "983040",
"model" : "Virtual Machine",
"numberOfCpu" : "1",
"vendor" : "Microsoft Corporation",
"vmList" : [ ],
"macadd" : [ ],
"cpuInfo" : "Intel(R) Xeon(R) CPU X5670 # 2.93GHz",
"memory" : "6188596",
"serialNo" : "00252-00000-00000-AA228",
"cpuUtilization" : 0,
}]
}
I want to access cpuUtilization from that json. I tried to access nested values using (.) but get result as NULL. I also tried to execute same on R shell but get result as NULL.
Here is what I have tried so far:
c.eval("query <- dbGetQuery(db,' mycollection','{\"hostId\":\"0.0.0.0\",\"windowsServer.cpuUtilization\":{\"$ne\":\"null\"},\"runtimeMillis\":{\"$ne\":\"null\"}}')");
c.eval("date <- query$runtimeMillis");
c.eval("host_id <- query$hostId");
c.eval("cpu <- query$Server.cpuUtilization");
c.eval("all_data<-data.frame(cpu,date)");
c.eval("training<- all_data");
c.eval("rf_fit<-randomForest(cpu~date,data=training,ntree=500)");
c.eval("new <- data.frame(date="+my_predicted_date+ ")");
c.eval("predictions<-predict(rf_fit,newdata=new)");
REXP memory_predictions= c.eval("predictions");
How do I access nested elements on either R shell or using java?
Dot notation should work in Java, I have been using it for quite a while now.
Check your code carefully, there might be a slight mistake somewhere.
Can you please post a part of your code here? I can then take a look and comment.
Here is what I normally do -
Lets say my document is like this -
{_id:0, start : {x:10, y:50}, end : {x:20, y:100}}
{_id:1, start : {x:20, y:50}, end : {x:30, y:100}}
{_id:2, start : {x:30, y:50}, end : {x:40, y:100}}
If I want to query based on "x" value in start field, I would write something like this:
MongoClient client = new MongoClient();
DB db = client.getDB("YourDBNAME");
DBCollection collection = db.getCollection("YOURCOLLECTIONAME");
QueryBuilder builder = QueryBuilder().start("start.x").greaterThan("20");
DBCursor cur = collection.find(builder.get());
while(cursor.hasNext())
{
System.out.println(cursor.next());
}
Compare this code snippet with yours and see. You should get it working fine.
Let me know if this helps or you need more help on this.

Categories