Using Cursor need to fetch values of Inner Json which is in Array
Document looks like this
{
"_id" : ObjectId("5772932ce4b0be6213704c81"),
"employerId" : "57728cd7e4b0be6213704b17",
"jobSeekerId" : "5706426ae4b0c7ea74fda18b",
"readByJobSeeker" : true,
"readByJobEmployer" : true,
"interestChat" : [
{
"userChat" : "is this job avaliable ",
"lastChatRole" : "JOBSEEKER",
"lastChatTime" : ISODate("2017-08-10T15:20:25.017Z"),
"jobSeekerAcknowledgeFlag" : true,
"connectionCounterIncreamented" : false
}
],
"createdDate" : ISODate("2016-06-28T15:09:32.564Z"),
"lastModifiedDate" : ISODate("2017-08-10T15:31:12.564Z"),
"version" : NumberLong(20),
"active" : true
}
Issue is using query
db.interest.find({"interestChat":{$exists:true}}).forEach(function(myChat){print ("interest :: "+ myChat.interestChat); } ).pretty()
Not able to fetch data from Array as output come out as
interest :: [object BSON]
Need to fetch values of Inner json
The function print is not meant to bring json/bson objects.
Try printjson instead.
db.interest.find({"interestChat":{$exists:true}})
.forEach(function(myChat){
printjson({"interest": myChat.interestChat});
})
OR just printjson(myChat.interestChat);
Related
I'm needing to retrieve just with two dates, all the documents from my MongoDB's collection, with the filtered items from the array.
This is an example of 2 of my documents;
{
"_id" : ObjectId("5f18fa823406b7000132d097"),
"last_date" : "22/07/2020 23:48:32",
"history_dates" : [
"22/07/2020 23:48:32",
"22/07/2020 00:18:53",
"23/07/2020 00:49:12",
"23/07/2020 01:19:30"
],
"hostname" : "MyHostname1",
"ip" : "142.0.111.79",
"component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
"process" : "LogonUI.exe",
"date" : "23/07/2020 10:26:04",
}
{
"_id" : ObjectId("5f18fa823406b7000132d098"),
"last_date" : "22/07/2020 23:48:33",
"history_dates" : [
"22/07/2020 23:48:33",
"23/07/2020 00:18:53",
],
"hostname" : "MyHostName2",
"ip" : "142.0.111.54",
"component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
"process" : "svchost.exe",
"date" : "23/07/2020 10:26:04",
}
I'm needing to make a find to my database (Using Spring Data), to retrieve the same objects, but with the "history_dates"'s array filtered between the 2 dates recieved.
For example, if my 2 recieved dates are: "23/07/2020" and "24/07/2020", I want MongoDB to return the next objects;
{
"_id" : ObjectId("5f18fa823406b7000132d097"),
"last_date" : "22/07/2020 23:48:32",
"history_dates" : [
"23/07/2020 00:49:12",
"23/07/2020 01:19:30"
],
"hostname" : "MyHostname1",
"ip" : "142.0.111.79",
"component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
"process" : "LogonUI.exe",
"date" : "23/07/2020 10:26:04",
}
{
"_id" : ObjectId("5f18fa823406b7000132d098"),
"last_date" : "22/07/2020 23:48:33",
"history_dates" : [
"23/07/2020 00:18:53"
],
"hostname" : "MyHostName2",
"ip" : "142.0.111.54",
"component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
"process" : "svchost.exe",
"date" : "23/07/2020 10:26:04",
}
I'm really ignorant about MongoDB's queries, and I have been trying to make this with Spring Data all the week.
UPDATE 1.
Thanks varman, and do you know how can i just retrieve the documents with filtered arrays not empty?
So basically you need to do filter. MongoTemplate offers a lot of operation for mongodb, if some methods don't exist in MongoTemplate, we can go with Bson Document pattern. In that case, try this article: Trick to covert mongo shell query.
Actually you need a Mongo query something like following. Using $addFields one of the methods shown below. But you can use $project, $set etc. Here $addFields overwrites your history_dates. (It uses to add new fields to document too).
{
$addFields: {
history_dates: {
$filter: {
input: "$history_dates",
cond: {
$and: [{
$gt: ["$$this", "23/07/2020"]
},
{
$lt: ["$$this", "24/07/2020"]
}
]
}
}
}
}
}
Working Mongo playground.
You need to convert this into spring data. So #Autowired the MongoTemplate in you class.
#Autowired
MongoTemplate mongoTemplate;
The method is,
public List<Object> filterDates(){
Aggregation aggregation = Aggregation.newAggregation(
a->new Document("$addFields",
new Document("history_dates",
new Document("$filter",
new Document("input","$history_dates")
.append("cond",
new Document("$and",
Arrays.asList(
new Document("$gt",Arrays.asList("$$this","23/07/2020")),
new Document("$lt",Arrays.asList("$$this","24/07/2020"))
)
)
)
)
)
)
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_CLASS.class), Object.class).getMappedResults();
}
Mongo template doesn't provide add methods for $addFields and $filter. So we just go with bson document pattern. I haven't tested this in Spring.
{
"_id" : ObjectId("577b54816081dd32cd3e2d60"),
"user" : ObjectId("577b54816081dd32cd3e2d5e"),
"journals" : [
{
"title" : "Journal Title2",
"desc" : "desx2",
"feeling" : 3,
"date" : ISODate("2016-07-05T06:32:45.404Z"),
"deleteFl" : true,
"_id" : ObjectId("577b548d6081dd32cd3e2d64")
},
{
"title" : "Journal Title3",
"desc" : "desx3",
"feeling" : 3,
"date" : ISODate("2016-07-05T06:49:00.156Z"),
"deleteFl" : false,
"_id" : ObjectId("577b585c6081dd32cd3e2d6d")
},
{
"title" : "Journal Title4",
"desc" : "desx4",
"feeling" : 3,
"date" : ISODate("2016-07-05T06:49:06.700Z"),
"deleteFl" : false,
"_id" : ObjectId("577b58626081dd32cd3e2d70")
}
]
}
Above is my document structure
now, I need all the journal documents whose deleteFl = false.
I tried in this way using Java Mongo driver
getDatabase().getCollection("journals").find(and(eq("user", user), eq("journals.deleteFl", false)));
but still it gives me back all the documents including "deleteFl": true. any help here ?
Actually, your query returns 1 document, because the data is inside 1 document. What you want is to limit the returning fields of a document (limit subdocuments).
Note: You can do that using elemMatch in the projection, to limit the fields returned by the query. But elemMatch will return just one subdocument. (I posted a deleted wrong answer using elemMatch)
When you want all subdocuments and only specific subdocuments from inside an array, you need to use the aggregation pipeline.
Here is a tested code that does what you want (just change DB and colelction name):
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection collection = db.getCollection("test");
Iterable<Document> output = collection.aggregate(asList(
new BasicDBObject("$unwind", "$journals"),
new BasicDBObject("$match", new BasicDBObject("journals.deleteFl", false))
));
for (Document dbObject : output)
{
System.out.println(dbObject);
}
I have a mongo collection named firma which has one of the document structure as below:
{
"_id" : ObjectId("5729af099b3ebf1d0ca7ff05"),
"musteriler" : [
{
"_id" : "de0bf813-b707-4a8d-afc2-9752e05c3aa5",
"yetkiliListesi" : [
{
"_id" : "a5e487fa-2034-4817-94f2-3bd837b76284",
"ad" : "Burak",
"soyad" : "Duman 1",
"cepTel" : "3333333333333",
"mail" : "asdf#asdf.com"
},
{
"_class" : "com.bisoft.entity.MusteriYetkili",
"_id" : "bc4b537d-522a-4c9a-9f67-8ca243e18f46",
"ad" : "Ridvan",
"soyad" : "ENİŞ",
"cepTel" : "222222222222",
"mail" : "asdf#asdf.com"
}
]
}
],
"defaultTimezone" : "Europe/Istanbul"
}
In the above json, I need to update element of second array(yetkiliListesi) which _id = "a5e487fa-2034-4817-94f2-3bd837b76284"
Since I am using a java application(using mongo java driver and spring boot MongoTemplate) to access it and execute this query :
mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is("5729af099b3ebf1d0ca7ff05").and("musteriler.yetkiliListesi._id").is("a5e487fa-2034-4817-94f2-3bd837b76284")),
new Update().set("musteriler.yetkiliListesi.$", yetkiliDBO), Firma.class);
In the above query, yetkiliDBO is a BasicDBObject and its content :
yetkiliDBO = {
'_class': 'com.bisoft.entity.MusteriYetkili',
'_id': "a5e487fa-2034-4817-94f2-3bd837b76284",
'ad': 'wer',
'soyad': 'xyz',
'cepTel': "222222222222",
mail: "asdf#asdf.com"
}
when execute my query I have an error
com.mongodb.WriteConcernException: { "serverUsed" : "192.168.2.250:27017" , "ok" : 1 , "n" : 0 , "updatedExisting" : false , "err" : "cannot use the part (musteriler of musteriler.yetkiliListesi.0) to traverse the element
What I need to do?
You can not use the '$' placeholder when traversing nested arrays.
The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value
source
I would suggest restructuring your data into separate, less-nested collections.
I am trying to add an element to a BasicDBList array and save it back to Mongodb, but when I check the result, it is not written. What did I do wrong? I use java driver version 2.7.2.
DBObject dbObject = coll.findOne(dbQuery);
BasicDBList unreadMsgs = (BasicDBList) dbObject.get("unreadMsgs");
Logger.debug("before incrementing unreadMsgs" + dbObject.toString());
unreadMsgs.add(new BasicDBObject("id", 1).append("unreadMsg", 1));
Logger.debug("after incrementing unreadMsgs : " + dbObject.toString());
coll.save(dbObject);
Logger.debug("check result: " + coll.findOne(dbQuery).toString());
before incrementing unreadMsgs{ "_id" : { "$oid" : "515c5eb88e3278e9c9d55867"} , "unreadMsgs" : [ ]}
after incrementing unreadMsgs : { "_id" : { "$oid" : "515c5eb88e3278e9c9d55867"} , "unreadMsgs" : [ { "id" : 1 , "unreadMsg" : 1}]}
check result: { "_id" : { "$oid" : "515c5eb88e3278e9c9d55867"} , "unreadMsgs" : [ ]}
The problem is that the coll.save(dbObject) is not updating anything.
It works as an insert and, since the _id already exists in the collection, you are getting a duplicateKey exception (you are just not seeing it because of configuration).
You have to use an update, here is how
The save call should work on that case, but I suggest you use an update with $addToSet operation.
Here's the code:
DBObject addToSetObj = BasicDBObjectBuilder.start()
.push("$addToSet")
.push("unreadMsgs")
.add("id", 1)
.add("unreadMsg", 1)
.pop()
.pop()
.get();
// addToSetObj will be { "$addToSet" : { "unreadMsgs" : { "id" : 1 , "unreadMsg" : 1}}}
coll.update(dbQuery, addToSetObj);
Logger.debug("check result: " + coll.findOne(dbQuery).toString());
Any doubts on how to use addToSet, check this out: http://docs.mongodb.org/manual/reference/operator/addToSet/
Thanks for everybody's answer. I found the real problem. It turns out that my collection is capped, and I am not allowed to insert more data into an existing document in a capped collection. I saw the exception after I changed WriteConcern to FSYNC_SAFE. I changed all my collections to uncapped, and the code works now.
I have a json object as following:
{ "_id" : ObjectId("508806803bb97dc546e6f307"), "user_name" : "user1", "user_id" : 45645645, "likes" : [ { "event_id" : NumberLong("4578541212") },{ "event_id" : NumberLong("4578541213") } ], "dislikes" : [ ] }
I'm trying to delete specific event within likes array via java drivers
tried doing this first in shell:
> db.users.update( {'likes.event_id' : 4578541212}, { '$unset':{'likes.event_id'
:1}})
with no luck...how can I manage doing that?
If you want to just remove the event_id field from the array element:
db.users.update( {'likes.event_id' : 4578541212}, {'$unset':{'likes.$.event_id' :1}})
Use the $pull operator to delete the element:
db.users.update({'likes.event_id': 4578541212}, {'$pull':{likes: {event_id: 4578541212}}})