首页 > 解决方案 > MongoDB aggregate, unwind, group (same array)?

问题描述

I have a MongoDB collection ("items") with the following schema:

const itemSchema = new mongoose.Schema({ 
  name: {
    type: String,
    required: true
    },
  description: String,
  categories: [String]
});

mongoose.model('Item', itemSchema, 'items');

Each item can have more than one category (categories [String]). I'm using the following javascript to try to get all the items grouped by the unwound categories array elements.

const itemsGetAllByCategory = function (req, res) { 
Item    
    .aggregate( [
            { '$unwind' : '$categories' }, 
            { '$group' : 
                { '_id': '$categories',
                    'elements': { '$push': 
                      {'name': '$name', 
                       'description': '$description' }
                    }
                }
            }
    ]) 
    .sort({'_id': 1})
    .exec((err, items) => {
        if (err) {
            res
              .status(404)
              .json(err);
        } 
        else {
            res
                .status(200)
                .json(items);
        }
    });
};

Data:

{
"_id" : ObjectId("5be0f88e7b1b91424006d597"),
"name" : "Item 1",
"description" : "Description of Item 1",
"categories" : "[\"Category A\", \"Category B\", \"Category C\"]"
}
{
"_id" : ObjectId("5be0f88e7b1b91424006d598"),
"name" : "Item 2",
"description" : "Description of Item 2",
"categories" : "[\"Category A\", \"Category B\"]"
}
{
"_id" : ObjectId("5be0f88e7b1b91424006d599"),
"name" : "Item 3",
"description" : "Description of Item 3",
"categories" : "[\"Category A\"]"
}

I would like the resulting output to be:

[{"_id":"Category A",
  "elements":[
   {"name":"Item 1","description":"Description of Item 1"},
   {"name":"Item 2","description":"Description of Item 2"}, 
   {"name":"Item 3","description":"Description of Item 3"}]},
 {"_id":"Category B",
  "elements":[
   {"name":"Item 1","description":"Description of Item 1"},
   {"name":"Item 2","description":"Description of Item 2"}]},
 {"_id":"Category B",
  "elements":[
   {"name":"Item 1","description":"Description of Item 1"}]}]

However, this code is giving me the following output:

[{"_id":"[\"Category A\", \"Category B\", \"Category C\"]",
  "elements":[
    {"name":"Item 1","description":"Description of Item 1"}]},
 {"_id":"[\"Category A\", \"Category B\"]",
  "elements":[
    {"name":"Item 2","description":"Description of Item 2"}]},
 {"_id":"[\"Category A\"]",
  "elements":[
    {"name":"Item 3","description":"Description of Item 3"}]}]

The $unwind call doesn't seem to be giving me the multiple output documents I expect for anything with more than one category, and the grouped categories remain as arrays instead of individual strings. Is there an issue with the code for unwind() or group() or both?

标签: javascriptmongodb

解决方案


原来问题出在数据库中:

categories: "[\"Category A\", \"Category B\", \"Category C\"]"

本来应该:

categories: ["Category A", "Category B", "Category C"]

左括号之前和右括号之后的引号导致条目被存储为单个字符串而不是字符串数组。感谢Neil Lunn建议我提供更多细节,这让我注意到了这一点。


推荐阅读