MongoDB:查找两个指定键值相等的项目

时间:2014-02-07 23:12:11

标签: node.js mongodb node-mongodb-native

我有一个mongoDB集合,集合中的项目如下所示:

{
"_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"
}

日期是ISODate对象。

此查询正确返回项目

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

下面的查询没有返回任何内容(我希望它返回上面的项目):

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

此查询返回所有项目(我再次预期会返回上面的项目):

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

我做错了什么? 谢谢!!

--- ---- EDIT

所以我尝试使用如下的小数据进行测试:

> 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")
}

您无法使用日期,因为您可以看到:

> 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")
}

适用于字符串值:

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

{ "title" : "samedescription" }

2 个答案:

答案 0 :(得分:1)

在比较JavaScript中的日期时,您必须非常小心 - 使用valueOf()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") }

这就是您的其他查询无效的原因。

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

这不起作用,因为您在初始化日期时没有使用new。这通常具有欢闹的结果,所有日期彼此相等:

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

但即使您使用new正确地实例化日期,在使用==比较日期时仍会获得热闹的结果,如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)

至于你的其他疑问:

  

如果我将它们视为字符串,它就无效了:

     

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

您实际上并没有将它们作为字符串进行比较,而是在比较ISODate个对象,这就是它们的存储方式。对于ISODate,类似于Date==运算符将返回false,除非您要比较完全相同的实例。但是,使用getTime应该可行,这就是我上面所做的。

希望这一切都没有任何意义,因为如果确实如此,我会担心你的理智。

答案 1 :(得分:0)

- 编辑 -

您正在寻找$where运营商。您的查询必须使用有效的JSON表示法,并且在此运算符之外,没有其他访问权限的原始JavaScript表示法。

日期

最后:

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

另外注意不要碰到保留字和其他陷阱。

非常小心阅读有关此运算符的文档,并确保您绝对需要它。由于您的查找将扫描整个集合,因此大大减慢速度。 无法使用索引。