0

Let's say this is my MongoDB schema:

    var shopSchema = new mongoose.Schema({
        nameShop: String,
        products: [
            {
                type: mongoose.Schema.Types.ObjectId,
                ref: 'Product'
            }]
    });

    var productSchema = new mongoose.Schema({
        nameProduct: String,
        fruits: [
            {
                type: mongoose.Schema.Types.ObjectId,
                ref: 'Fruit'
            }
        ]
    });

    var fruitSchema = new mongoose.Schema({
        nameFruit: String,
        price: Number
    });

module.exports = {
    Shop: mongoose.model('Shop', shopSchema),
    Product: mongoose.model('Product', productSchema),
    Fruit: mongoose.model('Fruit', fruitSchema)
}

I know that I can get data in this way, but result of that code is an "ugly" array

var Schema = require('../model/schema');
    Schema.Shop.find({}).populate({
        path: 'products',
        model: 'Product',
        populate: {
            path: 'fruits',
            model: 'Fruit'
        }
    }).exec(callback);

Is it possible to get data from this schema in way that I will have nice array? E.g.:

var MyArray = [
                  { nameShop: "Tesco", nameProduct: "New", nameFruit: "Apple", price: 10 },
                  { nameShop: "Tesco", nameProduct: "New", nameFruit: "Pinapple", price: 4 },
                  { nameShop: "Eko", nameProduct: "Old", nameFruit: "Kiwi", price: 8 },
                  { nameShop: "Makro", nameProduct: "Fresh", nameFruit: "Pear", price: 7 },
                  { nameShop: "Carefour", nameProduct: "New", nameFruit: "Orange", price: 6 }
              ];

enter image description here

1 Answer 1

1

You could go the aggregation framework route, which has the capacity to flatten the arrays through the $unwind operator. This will generate a new record for each and every element of the list data field on which unwind is applied. It basically flattens the data.

After flattening the data you would require the $lookup operator to do a "join" on the products field to the products collection. Repeat the process for the nested fruits schema.

Lets see an example (untested) to understand this better

var Schema = require('../model/schema');
Schema.Shop.aggregate([
    { "$unwind": "$products" },
    {
        "$lookup": {
            "from": "products",
            "localField": "products",
            "foreignField": "_id",
            "as": "product"
        }
    },
    { "$unwind": "$product" },
    { "$unwind": "$product.fruits" },
    {
        "$lookup": {
            "from": "fruits",
            "localField": "product.fruits",
            "foreignField": "_id",
            "as": "fruits"
        }
    },  
    {
        "$project": {
            "nameShop": 1,
            "nameProduct": "$product.nameProduct",
            "nameFruit": "$fruits.nameFruit",
            "price": "$fruits.price",
        }
    }
]).exec(function (err, result){
    if (err) throw err;
    console.log(result);
})

DISCLAIMER: The above is untested code which only serves as a guide by making a couple of assumptions that you are running the code in a test environment with the latest MongoDB and mongoose versions that support the $lookup operator AND that you can perform the same aggregation query in mongo shell.

Sign up to request clarification or add additional context in comments.

5 Comments

Result is Empty Array, anyway I'll try to fix this :)
This is result: prnt.sc/bmhft4 Inside is array with fruits I think you have misunderstood me. This is what I expected: prnt.sc/bmhnpg Is it even possible?
Any idea or should I find another solution because in that way it's impossible to get it?
So maybe should I create this array using foreach on my current "ugly" array?
Because in your example I can get only first Fruit from each Product

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.