简体   繁体   中英

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?

It turns out the issue was in the database:

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

should have been:

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

The quotes before the opening brackets and after the closing brackets were causing the entry to be stored as single strings rather than arrays of strings. Thanks to Neil Lunn for suggesting I provide more detail, which caused me to notice this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM