I've got the following document in MongoDB:
{
"_id" : NumberLong(44),
"_class" : "la.test.app.server.model.Event",
"orgId" : NumberLong(2),
"typeCode" : 1,
"title" : "Test for notification",
"shortDescription" : "Test for notification",
"description" : "Test for notification",
"price" : "100",
"startDate" : ISODate("2015-02-08T16:30:07.000Z"),
"endDate" : ISODate("2015-02-09T16:00:07.000Z"),
"deleted" : false
}
I need to find this event among all others.
I'm trying to do such a simple thing with method:
public List<Event> getPendingEvents(Date start, Date end) {
return mongoOperations.find(
Query.query(Criteria
.where("startDate").gte(start).lte(end)
.and("typeCode").is("1")),
Event.class
);
That assembles and returns me query:
{
"startDate" : { "$gte" : { "$date" : "2015-02-08T05:29:00.000Z"} ,
"$lte" : { "$date" : "2015-02-08T05:31:00.000Z"}} ,
"typeCode":"1"
}
And this query finds just "Fields: null, Sort: null":
But a direct query to MongoDB:
db.events.find({
"startDate" : {"$gte" : ISODate("2015-02-08 16:30:07.000Z"),
"$lt" : ISODate("2015-02-08 16:31:07.000Z")},
"typeCode" : 1})
Finds the required event.
Did you tried by formating the date by using SimpleDateFormat...?
I had tried this long back...
// Find documents by date of birth
Date gtDate = null;
try {
gtDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse("1984-05-010T8:30:00.000Z");
} catch (ParseException e) {
e.printStackTrace();
}
BasicDBObject dateQueryObj = new BasicDBObject("DateOfBirth", new BasicDBObject("$lt", gtDate));
cursor = documents.find(dateQueryObj);
while(cursor.hasNext()) {
System.out.println("\n Find documents by date of birth. \n");
System.out.println(cursor.next());
}
Same problem was solved by using BasicDBObject instead of a mongoOperations intreface.
Something like that:
BasicDBObject query = new BasicDBObject();
query = new BasicDBObject("endDate", new BasicDBObject("$gte", start).append("$lte", end)).append("typeCode", 1);
List<DBObject> result = collection.find(query).toArray();
Related
I have following document :
{
"_id" : ObjectId("5d42501efbf6f6108277ceb3"),
"customer" : {
"id" : "02c59458-8f0a-4a11-bff6-55b4710bc546",
"name" : "brookfield"
},
"userId" : "86c241de-16de-417d-8537-ed441fee9b0e",
"username" : "Fonville_f888f976_un_",
"userGroups" : [],
"lastSeen" : ISODate("2020-05-06T20:21:49.140Z"),
"devices" : [
{
"id" : "A920B6F24B63479B8796B709EA542951",
"displayId" : "A920B6F24B63479B8796B709EA542951",
"manufacturedId" : false,
"lastSeen" : ISODate("2020-03-20T14:36:24.961Z"),
"product" : {
"manufacturer" : "PSman",
"manufacturerCode" : 10,
"name" : "BlackHawk 880 series",
"modelId" : "C053"
}
},
{
"id" : "2476B0E045712cc-5904-11ea-af28-0612af3fc862",
"displayId" : "2476B0E16929512870992618563",
"lastSeen" : ISODate("2020-01-09T20:59:48.650Z"),
"product" : {
"manufacturer" : "GN",
"manufacturerCode" : 5,
"name" : "Telenor Speak 710",
"modelId" : "2476",
"vendorId" : "B0E"
}
}
],
"software" : {
"applicationId" : "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
"version" : "3.12.52334.30629",
"displayVersion" : "3.12.0"
},
"lastHost" : {
"name" : "hn_5934d3c5dbf",
"platform" : "WIN",
"osVersion" : "10.0.17763"
}
}
I have to update every product name inside devices array based on product modelId field.
So, user will pass two modelId values and if one of them match product's modelId than product name for that product should be updated.
I wrote following code, and I tested it with mongo db version 4.2, and it works. The problem is that when i tested it with older version of mongo db (3.4.23), it doesn't work,and I'm getting following exception :
com.mongodb.MongoCommandException: Command failed with error 9 (FailedToParse): 'Unrecognized field in update operation: arrayFilters' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "Unrecognized field in update operation: arrayFilters", "code" : 9, "codeName" : "FailedToParse" }
Here is how my method looks like :
private void updateCollection(String firstPid,String secondPid, String newProductName) {
MongoCollection<Document> collection = mongoTemplate.getCollection("user");
BasicDBObject searchQueryOne = new BasicDBObject();
BasicDBObject searchQueryTwo = new BasicDBObject();
BasicDBList or = new BasicDBList();
BasicDBObject query = new BasicDBObject("$or", or);
BasicDBObject updateQuery = new BasicDBObject();
searchQueryOne.append("devices.product.modelId", firstPid);
searchQueryTwo.append("devices.product.modelId", secondPid);
or.add(searchQueryOne);
or.add(searchQueryTwo);
updateQuery.append("$set",
new BasicDBObject().append("devices.$[elem].product.name", newProductName));
collection.updateMany(query, updateQuery, new UpdateOptions().arrayFilters(
Collections.singletonList( Filters.in("elem.product.modelId", Arrays.asList(firstPid,secondPid)))));
}
Please help
After some resarching, I managed to solve my problem. If someone have similar issue, here is the code that worked for me
public void updateUserCollection(String pidOne, String pidTwo) {
MongoCollection<Document> userCollection = mongoTemplate.getCollection("user");
BasicDBObject deviceCriteria = new BasicDBObject("devices.product.modelId", new BasicDBObject("$in", Arrays.asList(pidOne)));
FindIterable<Document> cursor = userCollection.find(deviceCriteria);
MongoCursor<Document> iterator = cursor.iterator();
while (iterator.hasNext()) {
Document user = iterator.next();
String userId = user.get("userId", String.class);
List<Document> devices = user.get("devices", List.class);
for (Document device : devices) {
Document product = device.get("product", Document.class);
String modelId = product.get("modelId", String.class);
if (modelId != null && (modelId.equals(pidOne) || modelId.equals(pidTwo))) {
product.put("name", newProductName);
}
}
saveUser(userId, user, userCollection);
}
iterator.close();
}
private void saveUser(String userId, Document user, MongoCollection<Document> userCollection) {
BasicDBObject updateQuery = new BasicDBObject("$set", user);
BasicDBObject searchQuery = new BasicDBObject("userId", userId);
userCollection.updateMany(searchQuery, updateQuery);
}
I have a collection "prefs" with document structure as below
{
_id: {
userId: "abc"
},
val: {
status: 1,
prefs: [
{
value: "condition",
lastSent: ISODate("2017-07-17T23:46:53.717Z")
}
],
deal: 2,
prevDeal: 3
}
}
I am trying to update the date field lastSent with a condition on userId and status. Below are the queries that I derieved from my Java code.
Select Query:
{ "_id" : { "userId" : "abc"} , "val.status" : 1 , "val.prefs.value" : "condition"}
Update Query:
{ "$set" : { "val.prefs.$.lastSent" : { "$date" : "2017-07-17T23:50:07.009Z"}}}
The above query is giving error as follows:
The dotted field 'prefs.$.lastSent' in 'val.prefs.$.lastSent' is not valid for storage.
How do I achieve this?
Below is my Java code:
BasicDBObject _idObject = new BasicDBObject();
_idObject.put("userId", "abc");
BasicDBObject _selectQuery = new BasicDBObject();
_selectQuery.put("_id", _idObject);
_selectQuery.put("val.status", 1);
_selectQuery.put("val.prefs.value", "condition");
BasicDBObject _valueUpdateQuery = new BasicDBObject();
_valueUpdateQuery.put("prefs.$.lastSent", lastSent);
BasicDBObject _updateQuery = new BasicDBObject();
_updateQuery.put("$set", new BasicDBObject("val", _valueUpdateQuery));
prefs.update(_selectQuery, _updateQuery, true, true);
I just tested with your code in mongo shell this codes works fine you don't have to mention
$date
and i used this code for updating date
db.getCollection('tester').update({ "_id" : { "userId" : "abc"} , "val.status" : 1 , "val.prefs.value" : "condition"},{ "$set" : { "val.prefs.$.lastSent" : new Date()}})
I've this document:
{
"_id" : ObjectId("54140782b6d2ca6018585093"),
"user_id" : ObjectId("53f4ae1ae750619418a20467"),
"date" : ISODate("2014-09-13T08:59:46.709Z"),
"type" : 0,
"tot" : 2,
"additional_info" : {
"item_id" : ObjectId("540986159ef9ebafd3dcb5d0"),
"shop_id" : ObjectId("53f4cc5a6e09f788a103d0a4"),
"ap_id" : ObjectId("53f4cc5a6e09f788a103d0a5")
},
"transactions" : [
{
"_id" : ObjectId("54140782b6d2ca6018585091"),
"date_creation" : ISODate("2014-09-13T08:59:46.711Z"),
"type" : -1
},
{
"_id" : ObjectId("54140782b6d2ca6018585092"),
"date_creation" : ISODate("2014-09-13T08:59:46.788Z"),
"type" : 1
}
]
}
and I need to add 2 more field to the first transaction opbject:
- date_execution: date
- result: this bson document
{ "server_used" : "xxx.xxx.xxx.xxx:27017" , "ok" : 1 , "n" : 1 , "updated_executed" : true} (m_OR.getDocument() in the following code example)
to obtaing that document
{
"_id" : ObjectId("54140811b6d25137753c1a1a"),
"user_id" : ObjectId("53f4ae1ae750619418a20467"),
"date" : ISODate("2014-09-13T09:02:09.098Z"),
"type" : 0,
"tot" : 2,
"additional_info" : {
"item_id" : ObjectId("540986159ef9ebafd3dcb5d0"),
"shop_id" : ObjectId("53f4cc5a6e09f788a103d0a4"),
"ap_id" : ObjectId("53f4cc5a6e09f788a103d0a5")
},
"transactions" : [
{
"_id" : ObjectId("54140811b6d25137753c1a18"),
"date_creation" : ISODate("2014-09-13T09:02:09.100Z"),
"type" : -1,
"result" : {
"server_used" : "xxx.xxx.xxx.xxx:27017",
"ok" : 1,
"n" : 1,
"updated_executed" : true
},
"date_execution" : ISODate("2014-09-13T09:02:15.370Z")
},
{
"_id" : ObjectId("54140811b6d25137753c1a19"),
"date_creation" : ISODate("2014-09-13T09:02:09.179Z"),
"type" : 1
}
]
}
The only way I was able to do that is the do 2 separates updates (update is a my wrapper funciont that execute the real updates in mongodb and it works fine):
// where
BasicDBObject query = new BasicDBObject();
query.append("transactions._id", m_Task.ID());
// new value for result - 1st upd
BasicDBObject value = new BasicDBObject();
value.put("$set",new BasicDBObject("transactions.$.date_execution",new Date()));
update(this._systemDB, "activities", query, value);
// new value for date_execution - 2nd upd
value = new BasicDBObject();
value.put("$set",new BasicDBObject("transactions.$.result",m_OR.getDocument()));
update(this._systemDB, "activities", query, value);
If I try to do this:
BasicDBObject value = new BasicDBObject();
value.put("$set",new BasicDBObject("transactions.$.date_execution",new Date()));
value.put("$set",new BasicDBObject("transactions.$.result",m_OR.getDocument()));
or = update(this._systemDB, "activities", query, value);
just the 2nd set will be applied.
Is there any way do avoid the double execution and apply the update with just one call?
Basic rule of "hash/map" objects is that you can only have one key. It's the "highlander" rule ( "There can be only one" ) applied in general reason. So just apply differently:
BasicDBObject value = new BasicDBObject();
value.put("$set",
new BasicDBObject("transactions.$.date_execution",new Date())
.add( new BasicDBObject("transactions.$.result",m_OR.getDocument() )
);
So basically "both" field arguments are part of the "$set" statement as in the serialized form:
{
"$set": {
"transactions.$.date_execution": new Date(),
"transactions.$.result": m_Or.getDocument()
}
}
Which is basically what you want in the end.
Your suggestion was right, just had to fix a little the syntax this way:
BasicDBObject value = new BasicDBObject();
value.put("$set",
new BasicDBObject("transactions.$.date_execution",new Date())
.append("transactions.$.result",m_OR.getDocument())
);
This worked perfectly ;)
Thanks!
Samuel
I am new to MongoDB. I am trying to access nested doc in mongodb. My sample doc is
{
"Advertisement" : {
"html" : "zxcxz"
},
"Notification" : {
"date_from" : ISODate("2013-06-30T18:30:00Z"),
"date_too" : ISODate("2013-07-16T18:30:00Z"),
"description" : "vcvc",
"url" : "vcvc"
},
"_id" : ObjectId("51e4f10ee4b08e0a6ebcbe46"),
"group_name" : "sumit",
"target_audience" : {
"gender" : "male",
"section" : "xyz",
"catagory" : "--Computer--",
"location" : {
"country" : "--Country--",
"state" : "--State--",
"city" : "--City--"
}
}
}
I am trying to get gender from target_audience. My java code is
DBCursor f=con.coll.find(query);
while(f.hasNext())
{
f.next();
gender=(String) f.curr().get("target_audience.gender");
}
But it returns null.
The result of DBCursor.next() and DBCursor.curr() is a BasicDBObject. For keys with embedded documents, BasicDBObject.get(key) returns a BasicDBObject
DBCursor f=con.coll.find(query);
while(f.hasNext())
{
BasicDBObject result = (BasicDBObject) f.next();
BasicDBObject target = (BasicDBObject) result.get("target_audience");
gender = (String) target.get("gender");
}
I am new to mongoDB. I am using java and mongoDB. I have a json like,
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "AA" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "AA" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "BB" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "BB" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
In a collection all doc's have different HomeTown, i just know the key name HomeTown, how can i get the HomeTown values?
In mongo site, i just can find find() and findOne().
Thanks!
find() is enough.
db.CollectionName.find({},{HomeTown:1})
in java, it would be:
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
field.put("HomeTown", 1);
DBCursor cursor = db.getCollection(collectionName).find(query,field);
while (cursor.hasNext()) {
BasicDBObject obj = (BasicDBObject) cursor.next();
result.add(obj.getString("HomeTown"));
}
db.CollectionName.find({},{HomeTown:1,PhoneNumber:0})
Would be wrong, but
db.CollectionName.find({},{HomeTown:1, _id:0})
would be right, because you need to suppress _id explicitly. Just FYI.
Mongo m = new Mongo('localhost',27017);
DB db = m.getDB("yourDBName");
Collection coll = db.getCollection("yourCollectionName")
BasicDBObject query = new BasicDBObject();
query.put("HomeTown", 1);
DBCursor cursor = coll.find(query);
ArrayList arr = new ArrayList();
String str;
while (cursor.hasNext()) {
str=cursor.curr().get("HomeTown").toString();
arr.add(str);
}
for(int value=0;value<=10;value++)
{
DBCollection tableDetails = db.getCollection("Collection Name");
BasicDBObject queryDetails = new BasicDBObject();
queryDetails.put("_id", value);
DBCursor cursorDetails =tableDetails.find(queryDetails);
DBObject oneDetails;
boolean Name=cursorDetails.hasNext();
while(Name)
{
oneDetails=cursorDetails.next();
String data=oneDetails.get("HomeTown").toString();
System.out.println(data);
}
}