1

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

更新添加了 Mongoid 查询 ,其 long for 中的查询是:

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 出现问题?

4

2 回答 2

2

我认为两者之间有区别:

avg_rating: {$exists: false}

这意味着返回字段不存在的结果

{"avg_rating"=>nil}

这限制了该字段存在但设置为 nil 的结果。

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

当为真时,$exists 匹配包含该字段的文档,包括字段值为空的文档。如果为 false,则查询仅返回不包含该字段的文档。

于 2014-03-27T02:16:15.553 回答
0

除了存在和是之间的区别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。

2014-03-27但是,MongoDB shell 在转换为时间戳时将使用当前有效的任何时区:

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

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

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

以确保您获得正确的时区。

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

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

于 2014-03-27T02:33:02.837 回答