2010-07-09 108 views
30

我知道如何通過多個字段對MongoDB中的查詢進行排序,例如db.coll.find().sort({a:1,b:-1})Mongo複雜排序?

我可以使用用戶定義的函數進行排序嗎?例如,假設a和b是整數,則a和b之間的差值爲(a-b)

謝謝!

+1

我遇到了同樣的問題。你能找到一種方法在服務器端實現這一點嗎?我真的寧願不必在客戶端上這樣做,或者添加額外的字段。 – 2011-03-09 19:17:52

回答

29

更新:此答案似乎已過時;似乎可以通過使用$project function of the aggregation pipeline在排序之前轉換輸入文檔或多或少地實現自定義排序。另見@阿里的回答。

我不認爲這是可能的直接; sort documentation肯定沒有提及任何提供自定義比較功能的方法。

您可能最擅長在客戶端進行排序,但如果您真的決定在服務器上執行此操作,則可以使用db.eval()安排在服務器上運行排序(如果您的客戶端支持它)。

服務器端排序:

db.eval(function() { 
    return db.scratch.find().toArray().sort(function(doc1, doc2) { 
    return doc1.a - doc2.a 
    }) 
}); 

對戰相當於客戶端排序:

db.scratch.find().toArray().sort(function(doc1, doc2) { 
    return doc1.a - doc2.b 
}); 

注意,它也可以通過aggregation pipeline進行排序,並通過$orderby operator(即除.sort())但是,這些方式都不能讓您提供自定義排序功能。

+2

是的。在進一步挖掘之後,我發現有一個RFE提交給方便的功能來完成這件事。我絕對不喜歡'toArray()'的外觀來看我的~10m文件,但這顯然是事態。 – gilesc 2010-07-09 14:56:23

+0

Hi @gilesc。請您告訴我您是如何完全使用「RFE提交」的細節?我處於同樣的情況。 – LotusH 2012-05-04 03:38:33

+1

@Wasabi我認爲他是指這個:https://jira.mongodb.org/browse/SERVER-153這是不可能的,但有一張票打開,他們正在考慮實施它。但它已開放多年,所以不知道它是否會發生。 – rmarscher 2012-05-09 17:03:52

11

爲什麼不用此操作創建字段並對其進行排序?

+3

我仍然需要單獨訪問a和b。所以我必須創建第三個領域。 這將適用於我的應用程序,但作爲一般原則將是非常糟糕的政策。假設我有幾個整數字段,將會有派生屬性(a-b),(a-c),(a-d)的組合爆炸......即使只有一個這樣的字段,對於大型集合來說也是浪費空間。 我upvoting,如果沒有人回答接受,但必須有一個更好的方法。在SQL中,這與「SELECT * FROM coll ORDER BY(a-b)'一樣簡單。 – gilesc 2010-07-09 13:39:15

+1

請注意,儘管您可以在SQL中執行此操作,但效率並不高。數據庫必須獲取所有a和b值,計算a-b,對結果進行排序並返回相關記錄。對於Mongo來說,這意味着如果你沒有a和b上的索引,那麼將所有文檔加載到內存中。如果你創建一個新的字段,你可以在這個字段上創建一個索引,這會使這個查詢真的很快。 – konrad 2013-01-06 16:03:16

+0

好主意。只要記錄位置的值本地化爲記錄本身的數據,就可以完美分攤計算插入/更新排序的成本。 – DoctorPangloss 2013-06-01 23:14:33

15

冉到這一點,這就是我想出了:

db.collection.aggregate([ 
    { 
    $project: { 
     difference: { $subtract: ["$a", "$b"] } 
     // Add other keys in here as necessary 
    } 
    }, 
    { 
    $sort: { difference: -1 } 
    } 
])