2014-03-27 55 views
1

使用Mongoid 3.1.5和MongoDB 2.4.9创建查询我从等价的MongoDB查询中得到了与Mongoid/Moped查询不同的结果。Mongoid Moped查询返回的结果与MongoDB shell不同

更新添加Mongoid查询 查询在其漫长的是:

return Video.order_by(release_date: :desc, avg_rating: :desc, title: :asc) 
.where(:viewable => true, :release_date.lte => start_at_date, :release_date.gte => 
start_date, :categories.in => genre_filters).any_of({:avg_rating.gt => 1}, 
{:avg_rating => nil}).skip(skip*POSTERS_PER_ROW).limit(limit*POSTERS_PER_ROW) 
.only(:_id, :poster_large_thumb, :title, :similar_as_string, :release_date, :avg_rating) 

此查询工作正常进行的一切我已经在它抛出时,除了要AFAIK发现genre_filters原因只有一个对象。

我得到以下控制台输出描述助力车查询:

MOPED: 127.0.0.1:27017 QUERY  database=guide_development collection=videos 
selector={"$query"=>{"viewable"=>true, "release_date"=>{"$lte"=>2014-03-27 00:00:00 UTC, 
"$gte"=>1850-01-01 00:00:00 UTC}, "categories"=>{"$in"=>["Netflix"]}, 
"$or"=>[{"avg_rating"=>{"$gt"=>1}}, {"avg_rating"=>nil}]}, "$orderby"=> 
{"release_date"=>-1, "avg_rating"=>-1, "title"=>1}} 
flags=[:slave_ok] limit=60 skip=0 batch_size=nil fields={"_id"=>1, 
"poster_large_thumb"=>1, "title"=>1, "similar_as_string"=>1, "release_date"=>1, 
"avg_rating"=>1} (198.0939ms) 

这不返回任何结果 - 不是我所期待。

一段时间后,我想出了以下MongoDB的外壳查询,它应该是等价的:

var start = new Date(2014, 3, 27); 
var end - new Date(1850,1,1); 

db.videos.find({ 
    viewable: true, release_date: { 
    $lte: start, $gte: end 
    }, 
    categories:{ 
     $in: ["Netflix"] 
    }, $or: [ {avg_rating: {$gt: 1}}, {avg_rating: {$exists: false}}], 
},{ 
    _id: 1, 
    poster_large_thumb: 1, 
    title: 1, 
    similar_as_string: 1, 
    release_date: 1, 
    average_rating: 1 
}).sort({release_date: -1, avg_rating: -1, title:1}).skip(0).limit(60).count() 

给出MongoDB的外壳一个结果,这是一个对象,应该找到。

任何想法?一个对象的结果在Mongoid中导致问题吗?

+0

请您提供示例文档吗? –

回答

2

我觉得有之间的差异:这意味着返回的结果

avg_rating: {$exists: false} 

当字段不存在

{"avg_rating"=>nil} 

这限制到现场,但存在结果设置为零。

请参阅该文档在这里:http://docs.mongodb.org/manual/reference/operator/query/exists/

如果是真的,$存在包含 领域,包括在字段值为空文件的文件相匹配。 如果 为false,则查询仅返回不包含 字段的文档。

+0

好吧,一个脚踏车{“avg_rating”=> nil}在shell中等同于什么?我只是想弄清楚为什么最初用Ruby编写的查询不起作用。如果我向Netflix添加另一个类别,比如说Mongoid中的“Horror”,那么同一个Moped查询会创建一个类别,所有查询都会返回一堆文档。唯一奇怪的事情似乎是只有一个文档拥有Netflix,或者查询中只有一个类别。 – pferrel

0

除了之外,您可能会遇到时区问题。

Rails和Mongoid将您的时间戳转换为UTC你,你可以在助力车日志中看到这一点:

"release_date"=>{"$lte"=>2014-03-27 00:00:00 UTC, "$gte"=>1850-01-01 00:00:00 UTC} 

Mongoid使用2014-03-27T00:00:00Z和1850-01-01T00 :00:00Z作为您的时间戳,因此您有00:00:00(UTC)作为时间组件。 MongoDB内部的时间戳也将采用UTC。

然而,MongoDB的外壳将使用什么时区是目前效果,当其转换2014-03-27到时间戳:

> new Date(2014, 3, 27) 
ISODate("2014-04-27T07:00:00Z") 

注07:00:00Z。这七个小时来自我的PDT时区(GMT-0700)。你应该使用ISODate便利功能在MongoDB的外壳正是如此:

> ISODate('2014-03-27') 
ISODate("2014-03-27T00:00:00Z") 
> ISODate('1850-01-01') 
ISODate("1850-01-01T00:00:00Z") 

,以确保你得到正确的时区。

此外,由于您只查看计数,因此您可以省略第二个参数到find到MongoDB shell以简化操作。或者使用{ _id: true }并放弃count()以减少混乱。

修复我和tirdadc指出的问题,看看在这两种情况下你是否得到相同的结果。如果你不这样做,那么开始逐个构建两个查询,直到它们产生不同的结果,并且你会知道问题出在哪里。不要忘记从一开始就包括排序选项,并比较返回的文档ID而不仅仅是计数。

+0

整个场景在我的开发机器上运行,所以时间区不是问题,我相信。优化查询是赞赏,但不是问题。我可能没有最佳查询,但为什么我会从一个数据库中得到一个结果,而在同一台机器上使用相同的数据库却无法获得结果。 – pferrel

+0

不要相信,验证。 'new Date(2014,3,27)'在MongoDB shell中说了些什么?切换到“ISODate”会改变什么吗? –

+0

我有其他order_by查询以不使用发布日期的方式进行排序,它们给出相同的结果,没有返回数据。我刚开始使用发布日期排序顺序,所以现在必须坚持下去。例如,按标题查询排序,不指定日期范围,当categories = [“Netflix”]时返回0,当categories = [“Horror”,“Netflix”]时返回一串。由于单张Netflix电影是一部恐怖电影,它会在任何指定类别的查询中返回=“[Horror”,“Netflix”] – pferrel