0

我試圖通過不同的客戶ID(CUSTID) 獲取不同的記錄相匹配的值指定的字段,分頁

  • 其中狀態代碼== 200
  • 讓我在MongoDB中收集

    • 所有文件
    • 分頁(跳過和限制)
    • 返回指定字段

    變種訂單= mongoose.model( '訂單',orderSchema());

    我最初的想法是使用mongoose db query,但你不能使用distinctskip and limitDistinct is a method that returns an "array", and therefore you cannot modify something that is not a "Cursor"

    Order 
         .distinct('request.headers.custID') 
         .where('response.status.code').equals(200) 
         .limit(limit) 
         .skip(skip) 
         .exec(function (err, orders) {  
          callback({ 
           data: orders 
          }); 
         }); 
    

    於是我想到要用Aggregate,使用$group得到不同的customerID記錄,$match返回所有唯一的客戶ID記錄的狀態碼爲200,並且$project包含我想要的字段:

    Order.aggregate(
         [ 
          { 
           "$project" : 
           { 
            'request.headers.custID' : 1, 
            //other fields to include 
           } 
          }, 
          { 
           "$match" : 
           { 
            "response.status.code" : 200 
           } 
          }, 
          { 
           "$group": { 
            "_id": "$request.headers.custID" 
           } 
          }, 
          { 
           "$skip": skip 
          }, 
          { 
           "$limit": limit 
          } 
         ], 
         function (err, order) {} 
        ); 
    

    儘管這會返回一個空數組。如果我刪除project,則只有$request.headers.custID字段返回,實際上我需要更多。

    有什麼想法?

    回答

    2

    您需要了解的關於聚合管道的事情通常是「管道」這個詞,意思是每個階段只接收由執行順序發出的前一階段輸入。想到這裏最好的模擬是「UNIX管道」 |,其中一個命令的輸出是「管道」其他:

    ps aux | grep mongo | tee out.txt 
    

    所以聚合管道在大致相同的方式進行,其他地方工作主要考慮的事項是$project$group階段的運作只發射你要求的領域,沒有其他人。與SQL等聲明式方法相比,這需要一些習慣,但稍加練習就會成爲第二性質。

    其他要習慣的東西是像$match這樣的階段對於放置在管線的開頭比放置字段更重要。主要原因是可能的索引選擇和使用,這極大地加快了速度。而且,$project後跟$group的字段選擇有點多餘,因爲無論如何都基本上選擇字段,並且通常在適當的情況下通常是最好的。

    因此最optimially你這樣做:

    Order.aggregate(
        [ 
         { "$match" : { 
          "response.status.code" : 200 
         }}, 
         { "$group": { 
          "_id": "$request.headers.custID", // the grouping key 
          "otherField": { "$first": "$otherField" }, 
          // and so on for each field to select 
         }}, 
         { "$skip": skip }, 
         { "$limit": limit } 
        ], 
        function (err, order) {} 
    ); 
    

    如果這裏最主要的是要記住的$group是所有其他領域比_id(這是分組鍵)需要使用accumulator的選擇,因爲實際上總是有多次出現分組鍵的值。

    在這種情況下,我們使用$first作爲累加器,它將從分組邊界開始第一次出現。通常在$sort之後使用,但不一定要這樣,只要你瞭解所選內容的行爲即可。

    $max其他蓄電池簡單地佔據場上的最大值從分組鍵內的值的範圍內,因此是「當前記錄/文件」不像$first$last的獨立的。所以這一切都取決於你的需求。

    當然你也可以用$$ROOT變量的MongoDB 2.6後shorcut在現代的MongoDB版本的選擇:

    Order.aggregate(
        [ 
         { "$match" : { 
          "response.status.code" : 200 
         }}, 
         { "$group": { 
          "_id": "$request.headers.custID", // the grouping key 
          "document": { "$first": "$$ROOT" } 
         }}, 
         { "$skip": skip }, 
         { "$limit": limit } 
        ], 
        function (err, order) {} 
    ); 
    

    這將需要各個領域的副本文件,並將它們命名項下(其在這種情況下是「文檔」)。這是一個更短的方式來表示,但當然,由此產生的文檔有不同的結構,現在都在一個關鍵字下作爲子字段。

    但是,只要您瞭解「管道」的基本原理,並且不會排除您希望在之前階段的後續階段中使用的數據,那麼您通常應該沒問題。

    +0

    超級有用布雷克斯。也爲解釋+1! – Growler

    相關問題