2014-03-27 54 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