Mongoid Moped查询不返回与MongoDB shell相同的查询

时间:2014-03-27 00:50:50

标签: ruby-on-rails mongodb mongoid mongoid3 moped

使用Mongoid 3.1.5和MongoDB创建查询2.4.9我从Mongoid / Moped查询得到的结果与MongoDB等效查询的结果不同。

更新添加的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)

除了genre_filters导致只有一个对象被发现之外,此查询对我所发送的所有内容都能正常工作。

我得到以下控制台输出,描述了Moped查询:

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 shell查询,它应该是等价的:

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 shell中给出一个结果,这是它应该找到的一个对象。

有什么想法吗?一个对象的结果是否会导致Mongoid出现问题?

2 个答案:

答案 0 :(得分:2)

我认为:

之间存在差异
avg_rating: {$exists: false}

表示返回字段不存在的结果

{"avg_rating"=>nil}

限制字段存在但结果为nil的结果。

请参阅此处的文档:http://docs.mongodb.org/manual/reference/operator/query/exists/

  

如果是,则$ exists匹配包含的文档   字段,包括字段值为null的文档。 如果   如果为false,则查询仅返回不包含的文档   字段。

答案 1 :(得分:0)

the difference between existence and is null旁边,您可能会遇到时区问题。

Rails和Mongoid会将您的时间戳转换为UTC,您可以在Moped日志中看到:

"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 shell将2014-03-27转换为时间戳时,它将使用当前有效的时区:

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

请注意07:00:00Z。那七个小时来自我的PDT时区(GMT-0700)。您应该在MongoDB shell中使用ISODate便利功能:

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

确保您获得正确的时区。

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

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