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

    相关问题