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).
Related
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));
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.
I have the following code, :
CommandResult cr = db.doEval("db." + collectionName + ".aggregate("
+ query + ")");
Command result is giving in batches, where I need to get in single value.
Batch Result:{ "serverUsed" : "/servername" , "retval" : { **"_firstBatch**" : [ { "visitor_localdate" : 1367260200} , { "visitor_localdate"
Expected Result:
{ "serverUsed" : "/servername" , "retval" : { "**result**" : [ { "visitor_localdate" : 1367260200} , { "visitor_localdate"
The Mongo DB we are using is 2.6.4 with 64 bit.
Can any one help with this?. I am guessing there is some Configuration issue.
Your doing this all wrong. You don't need to jump through hoops like this just to get a dynamic collection name. Just use this syntax instead:
var collectionName = "collection";
var cursor = db[collectionName].aggregate( pipeline )
Where pipeline also is just the array of pipeline stage documents, ie:
var pipeline = [{ "$match": { } }, { "$group": { "_id": "$field" } }];
At any rate the .aggregate() method returns a cursor, you can iterate the results with standard methods:
while ( cursor.hasNext() ) {
var doc = cursor.next();
// do something with doc
}
But you are actually doing this in Java and not JavaScript, so from the base driver with a connection on object db you just do this:
DBObject match = new BasicDBObject("$match", new BasicDBObject());
DBObject group = new BasicDBObject("$group", new BasicDBObject());
List pipeline = new ArrayList();
pipeline.add(match);
pipeline.add(group);
AggregationOutput output = db.getCollection("collectionName").aggregate(pipeline);
The pipeline is basically a list interface of DBObject information where you construct the BSON documents representing the operations required.
The result here is of AggregationOutput, but cursor like results are obtainable by additionally supplying AggregationOptions as an additional option to pipeline
There was something related to bacth added in mongodb 2.6, more details here: http://docs.mongodb.org/manual/reference/method/db.collection.aggregate/#example-aggregate-method-initial-batch-size
From the link
db.orders.aggregate(
[
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 2 }
],
{
cursor: { batchSize: 0 }
}
)
You might be having a cursor batch in your aggregate query
The answer from Neil Lunn is not wrong but I want to add that the result you were expecting is a result for mongodb versions earlier than v2.6.
Before v2.6, the aggregate function returned just one document containing a result field, which holds an array of documents returned by the pipeline, and an ok field, which holds the value 1, indicating success.
However, from mongodb v2.6 on, the aggregate function returns a cursor (if $out option was not used).
See examples in mongodb v2.6 documentation and compare how it worked before v2.6 (i.e. in v2.4):
Below is the JSON file from which I want to retrieve the phone number:
"_data" : {
"Variable key" : {
"Name" : "Hello World",
"Phone" : "Phone : 123-456-6789 ",
"Region" : "New York",
"Description" : ""
}
}
My Java Code is:
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
field.put("_data.Phone", 1);
DBCursor cursor = table.find(query,field);
String str;
while (cursor.hasNext()) {
BasicDBObject obj = (BasicDBObject) cursor.next();
str=cursor.curr().get("_data.Phone").toString();
System.out.println(str);
}
which will return null as I'm not considering the variable key.
My problem is there are many JSON files present in the mongo database each having different "Variable Key" and this key may change after sometime. As this key may change over time, how can I retrieve the phone number ?
Thank You !!
Which phone numbers do you want? Your query will return all documents and you are trying to project out just the phone number, but with an incorrect projection specification. If you want all phone numbers, just leave out the projection specification entirely or project on { "_data" : 1 }. If you want the phone numbers associated with specific variable keys, project those out using dot notation like { "_data.key_name.Phone" : 1 }. If you don't know the names of the keys that you want to project on, then that is your root problem that you need to solve before you ask MongoDB to return something that you don't know that you want (or that you don't want).
I am trying to write $in query with $regex in mongo+java. It's not working in mongo shell either. What I mean is I don't get any results but no query parse error either.
Here's the final query I got from Java Debugger at the line where I say collection.find(finalQuery)
{"$and": [
{"$or": [
{"country": "united states"}
]},
{"businesses": {
"$in": [
{"$regex": "^.*cardinal.*health.*$"},
{"$regex": "^.*the.*hartford.*$"}
]
}}
]}
Java Code snipet for Above query:
Set<Pattern> businesses = new HashSet<Pattern>();
for(String st: srchTerms) {
businesses.add(Pattern.compile("^"+st.trim()+"$"));
}
srchTermQuery.append("businesses", new BasicDBObject("$in", businesses));
However, following query works in mongo shell but I don't know how to write it into java:
{"registering_organization": {
"$in": [
/^.*cardinal.*health.*$/,
/^.*the.*hartford.*$/
]
}}
Java Code add double quotes around regex if we try to define it as a string.
The behavior you're seeing might be a bug, however as an alternative you can write your query like this
Pattern pattern = Pattern.compile("(^aaa$)|(^bbb$)");
srchTermQuery.append("businesses", pattern);
Not pretty but it seem to do the trick
You're not going to be able to convert:
{"businesses" : {
"$in":[
/^.*cardinal.*health.*$/,
/^.*the.*hartford.*$/
]
}}
directly into a Java regex. This is not a bug, it's because the Java driver uses $regex format when creating regex queries to avoid any ambiguity.
The $regex documentation states that
db.collection.find({field: /acme.*corp/});
db.collection.find({field: {$regex: 'acme.*corp'}});
So your Java-generated query of:
{"businesses": {
"$in": [
{"$regex": "^.*cardinal.*health.*$"},
{"$regex": "^.*the.*hartford.*$"}
]
}}
is exactly equivalent of the query you were trying to convert:
{"businesses": {
"$in": [
/^.*cardinal.*health.*$/,
/^.*the.*hartford.*$/
]
}}
In summary, the Java you've written is already the correct way to convert the query you wanted. I've run it in my own test and it returns the expected results.
Perhaps if you included some sample documents that you expect to be returned by the query we could help further?
I had a need to list all keys beginning with a specified string. The following worked for me in CLI:
db.crawlHTML.count({"_id": /^1001/})
The following was the Java implementation:
public List<String> listKeysLike(DB mongoDB, String likeChars) throws Exception {
DBCollection dbCollection = this.getHTMLCollection(mongoDB, TESTPROD);
List<String> keyList = new ArrayList<String>();
BasicDBObject query = new BasicDBObject();
String queryString = "^" + likeChars.trim() ; // setup regex
query.put("_id", java.util.regex.Pattern.compile(queryString));
DBCursor cursor = dbCollection.find(query);
while (cursor.hasNext()) { // _id used as the primary key
BasicDBObject obj = (BasicDBObject) cursor.next();
String tempString = obj.getString("_id");
keyList.add(tempString);
} // while
return keyList;
}
NB: The "TESTPROD" just tells me which of two databases I should be using.
You have to use mongodb regex notation rather than putting it in a string
db.somecollection.find({records: {$in: [/.*somestring.*/]}})