I have the following scenario.
I need to check multiple condition in a single update query.
Sample Data :
"host" : "zigwheels.com",
"lastAccessDate" : "20140819",
"sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"
Here is my requirement :
obj=db.userFrequency.find({"host" : "xyz.com", "sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"});
if(obj!=null){
if(obj.get("lastAccessDate")!= todayDate){
//If page has not visited today, increment count by 1 and update "lastAccessDate"=todayDate
db.userFrequency.update({"host" : "xyz.com","sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"},{$set : {"lastAccessDate"=todayDate},$inc : {"count":1}});
}
else{
// If page visited today{lastAccessDate==todayDate}, no need to update count
}
}else{
//Insert the new Entry
db.userFrequency.update({"host" : "xyz.com","sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"},{$set : {"lastAccessDate"=todayDate},$inc : {"count":1}},{upsert:true});
}
I need to do the above operation in a single query but I have GB's of data.
I tried above like below :
db.userFrequency.update({"host" : "xyz.com","lastAccessDate"!=todayDate,"sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"},{$set : {"lastAccessDate"=todayDate},$inc : {"count":1}});
but it inserts new entry because the above condition requires three checks.
Please suggest a solution for the same.
It's awkward if you store your date as a string. Store dates as date type fields and this is easy:
> db.userFrequency.insert({
"host" : "zigwheels.com",
"lastAccessDate" : ISODate("2014-08-19"),
"sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"
})
> var today = ISODate("2014-08-25")
> db.userFrequency.update({
"host" : "zigwheels.com",
"lastAccessDate" : { "$lt" : today },
"sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39"
},
{
$set : { "lastAccessDate" : today},
$inc : { "count" : 1 }
})
> db.userFrequency.findOne()
{
"_id" : ObjectId("53fbd08...398"),
"host" : "zigwheels.com",
"lastAccessDate" : ISODate("2014-08-25T00:00:00Z"),
"sessionId" : "ff8378ed-ccda-4a75-b24b-4a4bb1153e39",
"count" : 1
}
I used the $lt operator for the date test because users won't access the website from the future...hopefully. Using proper dates also surfaces another important issue- what timezone defines today? Right now, for me, it's tomorrow in Australia...
Related
I have to make an API whose endpoint will be like day=1&time=1000 and by using these query parameters I have to write a mongo query, JSON will be like
"_id" : ObjectId("62257ddd76b35400010e7015"),
"applyOffersOn" : [
{
"day" : 1,
"startTime" : NumberLong("1646625639561"),
"endTime" : NumberLong("1646631039561"),
"startTimeFormat" : NumberLong(930),
"endTimeFormat" : NumberLong(1100)
},
{
"day" : 2,
"startTime" : NumberLong("1646625639561"),
"endTime" : NumberLong("1646631039561"),
"startTimeFormat" : NumberLong(930),
"endTimeFormat" : NumberLong(1100)
},
{
"day" : 3,
"startTime" : NumberLong("1646625639561"),
"endTime" : NumberLong("1646631039561"),
"startTimeFormat" : NumberLong(1930),
"endTimeFormat" : NumberLong(2100)
}
],
}```
the query should be like I have to first check for a particular object using objectId then finding the object, check for the day is present as 1 and then check for the time that it will be between
startTimeFormat and endTimeFormat if all these conditions satisfy then return the whole object
I have written the query but it either works for the day or for a time but it should work like it check for both condition
I think this will help ,
##elemMatch - it will loop you through all elements of array.
const answer = <your model schema>.findById(req.params.id).find({applyOffersOn:{$elemMatch:{day:<your day from query> } }}).find({applyOffersOn:{$elemMatch : {startTimeFormat: {$lte:<your time from query> },endTimeFormat:{$gte:<your time from query>} }}})
I am familiar to simple mongodb queries but this one is a bit complex for me. Here, what I am trying to achieve is on the basis of jsonObject.callID and jsonObject.mobile fields I have to calculate time difference of jsonObject.timestamp. For example in below sample documents, jsonObject.callID and mobile will remain same for jsonObject.action start and end. So based on jsonObject.callID and jsonObject.mobile, I have to subtract the jsonObject.timestamp. jsonObject.callId will be same for two interval actions i.e. start and end with their same jsonObject.mobile numbers.
{
"_id" : ObjectId("5df9bc5ee5e7251030535df5"),
"_class" : "com.abc.mongo.docs.IvrMongoLog",
"jsonObject" : {
"mode" : "ivr",
"callID" : "33333",
"callee" : "128",
"action" : "end",
"mobile" : "218924535466",
"timestamp" : "2019-12-18 16:18:12"
}
}
{
"_id" : ObjectId("5df9bc3de5e7251030535df4"),
"_class" : "com.abc.mongo.docs.IvrMongoLog",
"jsonObject" : {
"mode" : "ivr",
"callID" : "33333",
"callee" : "128",
"action" : "start",
"mobile" : "218924535466",
"timestamp" : "2019-12-18 16:12:11"
}
}
So I am trying to achieve a output like below:
{
"callee" : "128",
"mobile" : "218924535466",
"callID" : "33333",
"minutes_of_call" : "6" // difference of "2019-12-18 16:18:12" - "2019-12-18 16:12:11"
}
subsequently I need such results for next documents...
Kindly assist.
I am trying to fetch total replies where read values for a replies is true. But I am getting count value as 3 but expected value is 2 (since only two read value is true) through Aggregation function available in Spring Data Mongo. Below is the code which I wrote:
Aggregation sumOfRepliesAgg = newAggregation(match(new Criteria().andOperator(Criteria.where("replies.repliedUserId").is(userProfileId),Criteria.where("replies.read").is(true))),
unwind("replies"), group("replies").count().as("repliesCount"),project("repliesCount"));
AggregationResults<Comments> totalRepliesCount = mongoOps.aggregate(sumOfRepliesAgg, "COMMENTS",Comments.class);
return totalRepliesCount.getMappedResults().size();
Using AND Operator inside Criteria Query and passed two criteria condition but not working as expected. Below is the sample data set:
{
"_id" : ObjectId("5c4ca7c94807e220ac5f7ec2"),
"_class" : "com.forum.api.domain.Comments",
"comment_data" : "logged by karthe99",
"totalReplies" : 2,
"replies" : [
{
"_id" : "b33a429f-b201-449b-962b-d589b7979cf0",
"content" : "dasdsa",
"createdDate" : ISODate("2019-01-26T18:33:10.674Z"),
"repliedToUser" : "#karthe99",
"repliedUserId" : "5bbc305950a1051dac1b1c96",
"read" : false
},
{
"_id" : "b886f8da-2643-4eca-9d8a-53f90777f492",
"content" : "dasda",
"createdDate" : ISODate("2019-01-26T18:33:15.461Z"),
"repliedToUser" : "#karthe50",
"repliedUserId" : "5c4bd8914807e208b8a4212b",
"read" : true
},
{
"_id" : "b56hy4rt-2343-8tgr-988a-c4f90598h492",
"content" : "dasda",
"createdDate" : ISODate("2019-01-26T18:33:15.461Z"),
"repliedToUser" : "#karthe50",
"repliedUserId" : "5c4bd8914807e208b8a4212b",
"read" : true
}
],
"last_modified_by" : "karthe99",
"last_modified_date" : ISODate("2019-01-26T18:32:41.394Z")
}
What is the mistake in the query that I wrote?
Could you guys tell me what I'm doing wrong ?
I have following document
{
"_id" : ObjectId("5013df3e4a4314271d002476"),
"bgtiled" : NumberLong(1),
"post_count" : NumberLong(0),
"url" : "fb_test",
"url_lower" : "fb_test",
"user_id" : NumberLong(4044217),
"verified" : NumberLong(0)
}
I want to increment post_count. According to documentation I do this
db.users.update({user_id : 4044217}, {$inc : {post_count : 1}});
and it doesn't increment the field. I also tried this
db.users.update({user_id : 4044217}, {$inc : {"post_count" : 1}});
and this
db.users.update({user_id : 4044217}, {"$inc" : {"post_count" : 1}});
with no result :(
If you were doing this in the shell, one way of finding out what is happening would be to check what getLastError() call returned on this update.
Since the shell automatically calls getLastError() for you on every entry, you can do it one of two ways:
> db.users.update({user_id : 4044217}, {$inc : {post_count : 1}})
> db.getPrevError()
{ "err" : null, "updatedExisting" : true, "n" : 1, "nPrev" : 8, "ok" : 1 }
Or you can getch the error before the shell calls GLE for you via
> db.users.update({user_id : 4044217}, {$inc : {post_count : 1}}); db.getLastErrorObj();
{
"updatedExisting" : false,
"n" : 0,
"connectionId" : 2,
"err" : null,
"ok" : 1
}
note: in the second example, GLE call must be on the same line as the update.
In your case it looks like you would have gotten back information that one existing document was updated, and that might have prompted you to check the find clause of your update statement via
> db.users.find( {user_id : 4044217} )
which would have returned more than one document.
Turned out I had multiple documents matching the query and only one was updated.
Sorry.
When i don't use pagination, everything works fine (i have only 3 records in this collection, so all of them are listed here):
db.suppliers.find({location: {$near: [-23.5968323, -46.6782386]}},{name:1,badge:1}).sort({badge:-1})
{ "_id" : ObjectId("4f33ff549112b9b84f000070"), "badge" : 3, "name" : "Dedetizadora Alvorada" }
{ "_id" : ObjectId("4f33ff019112b9b84f00005b"), "badge" : 2, "name" : "Sampex Desentupidora e Dedetizadora" }
{ "_id" : ObjectId("4f33feae9112b9b84f000046"), "badge" : 1, "name" : "Higitec Desentupimento e Dedetização" }
But when i try to paginate from the first to the second page, one record doesn't show up and one is repeated:
db.suppliers.find({location: {$near: [-23.5968323, -46.6782386]}},{name:1,badge:1}).sort({badge:-1}).skip(0).limit(2)
{ "_id" : ObjectId("4f33ff549112b9b84f000070"), "badge" : 3, "name" : "Dedetizadora Alvorada" }
{ "_id" : ObjectId("4f33feae9112b9b84f000046"), "badge" : 1, "name" : "Higitec Desentupimento e Dedetização" }
db.suppliers.find({location: {$near: [-23.5968323, -46.6782386]}},{name:1,badge:1}).sort({badge:-1}).skip(2).limit(2)
{ "_id" : ObjectId("4f33feae9112b9b84f000046"), "badge" : 1, "name" : "Higitec Desentupimento e Dedetização" }
Am i doing something wrong or is this some kind of bug?
edit:
Here is a workaround for this. Basically you shouldn't mix $near queries with sorting; use $within instead.
There is an open issue regarding the same problem. Please have a look & vote Geospatial result paging fails when sorting with additional keys