2017-02-17 121 views
4

我已經偶然發現了一些非常奇怪的行爲與MongoDB。對於我的測試用例,我有一個包含9個文檔的MongoDB集合。所有文件具有完全相同的結構,包括字段expired_at: Datelocation: [lng, lat]

我現在需要找到所有尚未過期的文檔,並且位於邊框內;我在地圖上顯示匹配文件。爲了這個,我設置了以下疑問:

var qExpiry = {"expired_at": { $gt : new Date() } }; 
var qLocation = { "location" : { $geoWithin : { $box : [ [ 123.8766, 8.3269 ] , [ 122.8122, 8.24974 ] ] } } }; 
var qFull = { $and: [ qExpiry, qLocation ] }; 

由於到期日是在過去的很長,當我設置邊框足夠大,下面的查詢給我所有9個文檔作爲預期:

db.docs.find(qExpiry); 
db.docs.find(qLocation); 
db.docs.find(qFull); 
db.docs.find(qExpiry).sort({"created_at" : -1}); 
db.docs.find(qLocation).sort({"created_at" : -1}); 

現在,這裏的交易:以下查詢返回0文件:

db.docs.find(qFull).sort({"created_at" : -1}); 

只是增加排序到與查詢遺址的結果(請注意,我要排序,因爲我也有一個利以避免在較大尺度上混亂地圖)。按其他字段排序會產生相同的空白結果。這裏發生了什麼?

(其實更奇怪:。當我放大到我的地圖,我有時會結果qFull,即使排序有人可能會說qLocation發生故障,但如果我只用qLocation,結果總是正確的,qExpiry對於所有文檔總是如此)

+2

您是否嘗試過使用聚合框架的'$ match'和'$ sort'管道運行相同的查詢? – chridam

+0

@chridam - 哇,這個伎倆!我會提供一個答案,因爲這似乎也是其他人可能遇到的問題。任何想法爲什麼這種方式工作,我的最初方法不是? – Christian

回答

2

你可能想嘗試使用聚合框架的$match$sort管道運行相同的查詢:隱含使用$and通過specifiying一個逗號分隔的表達式列表中

db.docs.aggregate([ 
    { "$match": qFull }, 
    { "$sort": { "created_at": -1 } } 
]); 

db.docs.aggregate([ 
    { 
     "$match": { 
      "expired_at": { "$gt" : new Date() }, 
      "location" : { 
       "$geoWithin" : { 
        "$box" : [ 
         [ 123.8766, 8.3269 ], 
         [ 122.8122, 8.24974 ] 
        ] 
       } 
      } 
     } 
    }, 
    { "$sort": { "created_at": -1 } } 
]); 

不太清楚爲什麼失敗find()

1

chridam使用MongoDB的聚合框架的建議被證明是要走的路。我的工作查詢現在看起來是這樣的:

db.docs.aggregate(
    [ 
     { $match : { $and : [qExpiry, qLocation]} }, 
     { $sort: {"created_at": -1} }. 
     { $limit: 50 }. 
    ] 
); 

不過,如果任何能指出我的方式第一種方法不奏效,這將是非常有用的。簡單地將sort()添加到非空查詢不應該突然返回0個文檔。只是補充一點,因爲我仍然嘗試了一下,.sort({})返回所有文件,但是不是很有用。其他一切都失敗了,包括.sort({'_id': 1})