0

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.

1 Answer 1

2

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...

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the suggestion, i'll use date type fields to store date but It is not fulfilling the second "if condition" as i have described in the first post because if a user has visited today already,then its "lastAccessDate":todayDate. So, when we comes to third condition,"lastAccessDate":{$lt : todayDate} , it fails and upsert the new entry.
If lastAccessDate in a document is today, then it is not $lt today, so the document will not match the update criteria and will not be updated. There is no upsert : true option set, so no new document will be inserted.
If don't set the upsert:true condition, then can we handle the entry for a new visitor(who is visiting page first time)
If you set upsert : true, it looks like everything would be fine. If there's no matching doc, it inserts a new one with the given sessionId and host, a lastAccessedDate of today, and a count of 1.
I tried a lot... could you please give me a working query,,, as i tried a lot and getting duplicate entries again and again.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.