2017-02-09 76 views
1

有什麼方法可以獲取聚合中的最後一個非零值。那可能嗎?

場景:

我有一個事件集合,其中我從存儲用戶的所有事件。我想獲取上次購買物品的用戶列表,費用爲1.99美元,並且上週至少登錄過一次。

我的活動集合將有記錄,如

{_id:ObjectId("58af54d5ab7df73d71822708"),uid:1,event:"login"} 
{_id:ObjectId("58db7189296fdedde1c04bc1"),uid:2,event:"login"} 
{_id:ObjectId("5888419bfa4b69dc4af7c76c"),uid:2,event:"purchase",amount:3} 
{_id:ObjectId("5888419bfa4b69dc4af7d45c"),uid:1,event:"purchase",amount:1.9} 
{_id:ObjectId("5888819bfa4b69dc4af7c76c"),uid:1,event:"custom",type:3,value:2} 

什麼我試圖做的事:

db.events.aggregate([{ 
     { 
     $group: { 
      _id: uid, 
      last_login: { 
      $max: { 
       $cond: [{ 
       $eq: ['$event', 'login'] 
       }, '$_id', 0] 
      } 
      }, 
      last_amount: { 
      $last: { 
       $cond: [{ 
       $eq: ['$event', 'login'] 
       }, '$_id', 0] 
      } 
      } 
     } 
     } 
    }, { 
     $match: { 
     last_purchase: { 
      $gte: ObjectId("58af54d50000000000000000") 
     }, 
     last_amount: 1.9 
     } 
    }]) 

這顯然會失敗,因爲最後將0作爲最後一個項目。

輸出很期待是

{_id:1,last_login:_id:ObjectId("58af54d5ab7df73d71822708"),last_amount:1.9} 

查詢是系統生成的。請幫忙。

+0

新增樣本文件和預期產出 –

回答

0

要回答你的問題,你不能使用$ cond修改$ last的行爲。即「由於標準而不是最後一個條目」。 有跡象表明,你可以嘗試一些替代方案:

  • 改變你document schema的接入模式,尤其是如果這是在應用程序中經常使用的查詢。您應該利用架構作爲優化您的應用程序查詢的槓桿。
  • 使用MongoDB supported drivers之一來處理預期結果。
  • 根據用例,您可以執行2個單獨的聚合查詢;首先查詢上週至少登錄一次的所有用戶uid,然後查詢上次購買的物品價值爲1.99美元的用戶。
+0

嗨伊萬, 謝謝。但我找到了一個替代方法來做到這一點。我在分組中使用了$ push,在$ project中使用了$ slice和$ setDifference –

0

我找到了一個解決方法。替代$ last,我在$ group中使用了$ push,並在$ project中添加了$ slice和$ setDifference以刪除空值。查詢現在看起來像

db.events.aggregate([{ 
 
      { 
 
      $group: { 
 
       _id: uid, 
 
       last_login: { 
 
       $max: { 
 
        $cond: [{ 
 
        $eq: ['$event', 'login'] 
 
        }, '$_id', 0] 
 
       } 
 
       }, 
 
       last_amount: { 
 
       $push: { 
 
        $cond: [{ 
 
        $eq: ['$event', 'login'] 
 
        }, '$_id', null] 
 
       } 
 
       } 
 
      } 
 
      } 
 
     }, 
 
    {$project:{last_login:{$slice:[{$setDifference,'$last_login',[null]},-1,1]}}} 
 
    , { 
 
      $match: { 
 
      last_purchase: { 
 
       $gte: ObjectId("58af54d50000000000000000") 
 
      }, 
 
      last_amount: 1.9 
 
      } 
 
     }])