Pregunta

I have a mongoDB collection and an item in the collection looks like below:

{
"_id": "52f535b56268a019bd11cc2a",
"description": "Some description",
"entry_date": "2014-02-07T19:36:21.430Z",
"last_update": "2014-02-07T19:36:21.430Z",
"r": "samestring",
"s": "samestring"
}

Dates are ISODate objects.

This query returns items correctly

db.myCollection.find({$where : "this.entry_date < this.last_update"});

Below query returns nothing (I expect that it returns the above item):

db.myCollection.find({$where : "this.entry_date == this.last_update"});

And this query returns all items (I expected again it returns the above item):

 db.myCollection.find({$where :"this.r == this.s"});

What am I doing wrong? Thanks!!

---EDIT----

So I tried to test with a small data like below:

> db.myCollection.find({},{ _id: 0, start_date: 1, end_date: 1});

{ 
   "start_date" : ISODate("2014-02-07T19:36:21.430Z"),
   "end_date" : ISODate("2014-02-07T19:36:21.430Z") 
}
{  
   "start_date" : ISODate("2014-02-07T19:36:21.430Z"),
   "end_date" : ISODate("2014-02-07T22:39:02.114Z")
}

It didn't work for Date as you can see:

> db.myCollection.find(
    {$where: "Date(this.start_date) == Date(this.end_date)"},
    { _id: 0, start_date: 1, end_date: 1 }
  );



{
    "start_date" : ISODate("2014-02-07T19:36:21.430Z"),
    "end_date" : ISODate("2014-02-07T19:36:21.430Z") 
}
{
    "start_date" : ISODate("2014-02-07T19:36:21.430Z"),
    "end_date" : ISODate("2014-02-07T22:39:02.114Z")
}

Works for string values:

> db.myCollection.find({$where: "this.title == this.description"},{ _id: 0, title: 1 });

{ "title" : "samedescription" }
¿Fue útil?

Solución

You have to be really careful when comparing dates in JavaScript - use valueOf() or getTime():

> db.myCollection.find({$where: "this.start_date.getTime() == this.end_date.getTime()"});

{ "_id" : ObjectId("52f5b7e316d795f0a076fbdf"), "description" : "a description", "title" : "a title", "start_date" : ISODate("2014-02-07T19:36:21.430Z"), "end_date" : ISODate("2014-02-07T19:36:21.430Z") }

Here is why your other queries didn't work.

db.myCollection.find({$where: "Date(this.start_date) == Date(this.end_date)"});

This didn't work because you didn't use new when initializing the dates. This generally has hilarious results with all dates being equal to each other:

> Date(2014,2,8) == Date(1941,12,7)
true
> Date(2000,1,1) == Date(1995,2,8)
true

But even if you properly instantiate the date using new, you still get hilarious results when comparing dates using ==, as demonstrated in this gist:

var dateValue = 504001800000; // Saturday, December 21st, 1985 at 3:30am EST
var date1 = new Date(dateValue);
var date2 = new Date(dateValue);

console.log(date1 == date2);  // false (different instances)
console.log(date1 === date2); // false (different instances)
console.log(date1 > date2);   // false (date1 is not later than date2)
console.log(date1 < date2);   // false (date1 is not earlier than date2)
console.log(date1 >= date2);  // true (rofl)
console.log(date1 <= date2);  // true (ahahahaha)

As for your other query:

It didn't work if I consider them as strings either:

db.myCollection.find({$where: "this.start_date == this.end_date"});

You're not actually comparing them as strings, you're comparing ISODate objects, which is how they're stored. For ISODate, similar to Date, the == operator will return false unless you're comparing the exact same instance. Using getTime should work, however, which is what I did up above.

Hopefully, none of this makes any sense whatsoever, because if it does, I'm worried about your sanity.

Otros consejos

--EDITED--

You were looking for the $where operator. Your query must be in a valid JSON notation and outside of this operator there is no other access to that kind of raw JavaScript notation.

Dates

finally:

{$where: "this.start_date.valueOf() == this.end_date.valueOf()"}

Also be careful not to run into reserved words and other traps.

Be very careful to read the documentation on this operator and make sure you absolutely need it. It will slow things down considerably as your find will scan the entire collection. It cannot use an index.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top