admin管理员组

文章数量:1384149

Given these documents:

db.orders.insert( {OrderId:1, OrderItems: [{OrderItemId:1, Qty:1}, {OrderItemId:2, Qty:1} ]} );
db.orders.insert( {OrderId:2, OrderItems: [{OrderItemId:1, Qty:1}, {OrderItemId:2, Qty:2} ]} );

I'd like to get the count of all OrderItems where the Qty = 1 (expected result 3). This is how I think to write the query, but it returns 2 (1 for each Order document):

db.orders.find({"OrderItems.Qty":1}).count();

How can I query to find the count of all OrderItems where the Qty = 1?

Given these documents:

db.orders.insert( {OrderId:1, OrderItems: [{OrderItemId:1, Qty:1}, {OrderItemId:2, Qty:1} ]} );
db.orders.insert( {OrderId:2, OrderItems: [{OrderItemId:1, Qty:1}, {OrderItemId:2, Qty:2} ]} );

I'd like to get the count of all OrderItems where the Qty = 1 (expected result 3). This is how I think to write the query, but it returns 2 (1 for each Order document):

db.orders.find({"OrderItems.Qty":1}).count();

How can I query to find the count of all OrderItems where the Qty = 1?

Share Improve this question edited Jul 3, 2010 at 0:49 whitez asked Jul 2, 2010 at 23:20 whitezwhitez 412 silver badges4 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 4

Just to be clear for others reading this thread.

The OP's mand db.orders.find({"OrderItems.Qty":1}).count(); basically counts the number of Documents where any order item has a quantity of 1.

However, the OP wants a count of all OrderItems where the quantity is one. The problem here is that we're not counting Documents. We're counting items within an array within a Document. Hence the need for javascript and some form of special reduce operation.

You could use JavaScript:

db.orders.group(
{
  key: null, 
  cond: {'OrderItems.Qty':1}, 
  initial: {count: 0}, 
  reduce: function(el, running)
  {                                                                                                       
    running.count += el.OrderItems.filter(function(el)                                                    
    {                                                                                                     
      return el.Qty == 1;                                                                                 
    }).length;                                                                                            
  }                                                                                                       
});

This should do it for you in the shell without JavaScript (so it'll be a lot quicker);

db.orders.aggregate([
  {$unwind:'$OrderItems'},
  {$match: {'OrderItems.Qty':1}},
  {$group : { 
      _id : "Qty1",
      sum: {$sum:1}
  }}
]);

Although it's unfortunate your data is structured like that if this is a mon query. Having to do an $unwind is relatively expensive. It's a shame your order items aren't laid out as separate documents tagged with the order ID instead of orderID documents containing arrays of order items...in other words, the reverse of what you have. That would be much easier and more efficient to process.

db.orders.aggregate([
  {$unwind: '@OrderItems'},
  {$match : {'OrderItems.Qty':1}},
  {$group : { _id : null, 'countOfQty1':{$sum:'$OrderItems.Qty'} }}
]);

本文标签: javascriptMongoDB Get count of ArrayStack Overflow