Scott Allen
Scott Allen

Reputation: 533

Cloudant View Unusual Conditional Behavior with Dates

Found some peculiar behavior was wondering if anyone could help me to understand it so to avoid similar issues in the future.

Creating a cloudant view I want to return only records with a timestamp of the current day.

I was having a hard time getting it to work and found the difference is in having a space before the end of the if condition.

See below for working and not working

 if (new Date(Date.parse(doc.details.timestamp)).setHours(0,0,0,0) === new Date().setHours(0,0,0,0) ){

Works to check the current date against the Cloudant doc date

 if (new Date(Date.parse(doc.details.timestamp)).setHours(0,0,0,0) === new Date().setHours(0,0,0,0)){

Does not work to check the date against the Cloudant doc date

Full working view below for context

function (doc) {
  if (doc.details.location){
    if (new Date(Date.parse(doc.details.timestamp)).setHours(0,0,0,0) === new Date().setHours(0,0,0,0) ){
      emit(doc.details.location.toLowerCase(), { "location": doc.details.location.toLowerCase(), "status": doc.details.status, "user": doc.details.username, "time": doc.details.timestamp})
    }
   }
 }

All the best,

Scott.

Upvotes: 1

Views: 170

Answers (1)

Mike Rhodes
Mike Rhodes

Reputation: 1836

I suspect this may be to do with the execution date/time of the if statement rather than the space involved.

The map function needs to be deterministic regardless of execution time.

It looks like you are guessing that the map function is running at query time (so new Date would emit today's date). Instead, it runs at indexing time, so the value of new Date is whatever the datetime is when the indexing happens. As indexing runs at a different time to document insertion (sometime between insert and when the view is queried), using any form of value that changes with time will produce unpredictable results.

I suspect therefore the space is co-incidental and instead the output of new Date is changing, and so altering what's emitted into your view.

For your problem -- querying for things "today" -- I think you want to instead emit a key like [location, year, month, day]. Your map function would look like:

function (doc) {
  if (doc.details.location) {
    var l = doc.details.location.toLowerCase();
    var d = Date.parse(doc.details.timestamp);
    emit([l, d.getFullYear(), d.getMonth(), d.getDate()], { 
      "location": l, 
      "status": doc.details.status, 
      "user": doc.details.username, 
      "time": doc.details.timestamp
    });
  }
}

As JavaScript uses 0-based indexes for the month, to query for all items at location Bristol on today, 2-Feb-2017, you'd use key=["bristol",2017,1,2] to in your query to the view.

Upvotes: 3

Related Questions