2014-09-27 12 views
1

我有幾個對象需要執行不區分大小寫的排序。我被告知我不能將陰影列添加到數據庫以正常化值。由於這個,我正在使用聚合來排序我的輸出。是否有更好的方式在MongoDB中進行不區分大小寫排序而不使用陰影列?

我也表示爲這樣一個簡單的對象:

_id:該對象ID

createdOn:時間創建對象

lastUpdatedOn:Time對象最後更新

名稱:名稱的對象

isActive:表示對象當前是否處於活動狀態的布爾值

這是我的聚集函數:

db.organization.aggregate(
    [ 
     { 
      $match: { isActive: true } 
     }, 
     { 
      $project: { 
         lastUpdatedOn: 1, 
         createdOn: 1, 
         name: 1, 
         normalizedName: {$toLower: "$name"} 
         } 
     }, 
     { 
      $sort: { normalizedName: 1 } 
     }, 
     { 
      $project: { 
         lastUpdatedOn: 1, 
         createdOn: 1, 
         name: 1 
         } 
     } 
    ] 
) 

它首先可以確保我們只處理活動對象,我們的排序創建標準化領域,進行排序,然後刪除標準化字段,以便它不是」暴露給用戶。它的工作原理是根據名稱字段按字母順序排列所有對象,但我不知道是否有更好的方法。

回答

2

它不一定是一個顯着的改善,但根據您的具體使用情況,投影$$ROOT捕捉原始文檔從臨時排序列單獨的可清潔:

db.organization.aggregate(
    [ 
     { 
      $match: { isActive: true } 
     }, 
     { 
      $project: { 
         doc: '$$ROOT' 
         normalizedName: {$toLower: "$name"} 
         } 
     }, 
     { 
      $sort: { normalizedName: 1 } 
     }, 
     { 
      $project: { doc: 1 } 
     } 
    ] 
) 

缺點是你結束了你的原始文檔在doc屬性中,但這很容易通過類似Array#map清理客戶端。或者您可以修改最終的$project以將每個字段提升到頂層,但這可能很乏味。

0

雖然MondoDB不提供它,但您可以非常容易地使用PHP或任何其他語言。這是如何在PHP中完成的。

$cn = new MongoClient($dbHost); 
$db = $cn->selectDB($dbName); 
$col = new MongoCollection($db, $collectionName); 

$cursor = $col->find(); 
$cursor = iterator_to_array($cursor); 

foreach ($cursor as $key => $row) { 
    $name[$key] = $row['name']; 
    $email[$key] = $row['email']; 
} 
//$name is the field to sort on, taken from the above loop 
//You can use SORT_ASC or SORT_DESC 

array_multisort($name, SORT_ASC, $cursor); 

foreach ($cursor as $doc) { 
    echo $doc['name'].'-'.$doc['email'].'<br/>'; 
} 
+0

不要做這種方式。您正在將整個集合加載到內存中。如果你的集合大於你的php內存限制,你會得到一個內存不足的錯誤。順便說一句:無論如何你要循環使用iterator_to_array會浪費它。 – 2016-04-19 16:13:59

+0

同意,這不是方式,但只是一個出路。 – phpMax 2016-04-21 03:31:15

0

我意識到這是一個老問題,但由於蒙戈3.4 Collation支持,這使得這更簡單。對於Collat​​ion聚合,只需添加如下所示的排序對象: db.organization.aggregate([pipelineobjs],{collation: {locale:'en_US'}})

我相信你的特定集合會是什麼樣子:

db.organization.aggregate(
    [ 
     { 
      $match: { isActive: true } 
     }, 
     { 
      $project: { 
         lastUpdatedOn: 1, 
         createdOn: 1, 
         name: 1 
         } 
     }, 
     { 
      $sort: { name: 1 } 
     }, 
     { 
      $project: { 
         lastUpdatedOn: 1, 
         createdOn: 1, 
         name: 1 
         } 
     } 
    ], 
    {collation: {locale:'en_US'}} 
) 
相關問題