Невозможно заполнить мои поля с помощью populate()

Это моя модель product.js

const mongoose = require("mongoose");
const { Schema } = mongoose;

const productsSchema = new mongoose.Schema({
    name: {
        type: String,
        required: [true, "Name is required"]
    },
    imgURL: {
        type: String,
        required: [true, "imgURL is required"]
    },
    description: {
        type: String,
        required: [true, "Description is required"]
    },
    categoryName: {
        type: String,
        required: [true, "Category is required"]
    },
    price:{
        type: Number,
        required: [true, "Price is required"],
        default: false
    },
    isActive:{
        type: Boolean,
        default: true
    },
    variations: {
        size:[
            {
            type: Schema.Types.ObjectId,
            ref: 'Size'
            }
        ]
    }
})

const Products = mongoose.model('Products', productsSchema);

module.exports = Products;

и вот мой код:

const Products = require("../models/products");
const Size = require("../models/size")

module.exports.createProduct = (req,res) => {
    if (!req.user.isAdmin) {
        return Promise.reject("Only administrators can create products")
    }

    const newProduct = new Products ({
        name: req.body.name,
        imgURL: req.body.imgURL,
        description: req.body.description,
        categoryName: req.body.categoryName,
        isActive: req.body.isActive,
        price: req.body.price
    });

    return newProduct.save()
    .then(() => {
        return res.send(true);
    })
    .catch((error) => {
        console.error(error);
        if (error.name === 'ValidationError') {
            return res.status(400).json({message: 'Validation Error', errors: error.errors});
        }
        return res.status(500).json({message: 'Internet server error'});
    });
};


module.exports.getAllActiveProducts = (req, res) => {
    Products.find({ isActive: true })
            .populate({ path: 'variations.size', model: 'Size'})

        .then(result => {
            console.info("Found products with variations:", result);
            return res.send(result);
        })
        .catch(err => {
            console.error("Error fetching active products:", err);
            return res.status(500).json({ error: "Failed to fetch active products" });
    });
};

Это моя модель размера

const mongoose = require("mongoose");

const sizeSchema = new mongoose.Schema({
    name: {
        type: String,
        required: [true, "Size is required"]
    },
    isActive: {
        type: Boolean,
        default: true
    }
})

const Size = mongoose.model('Size', sizeSchema);

module.exports = Size;

Я хочу заполнить поле размера, но, похоже, у меня возникла проблема с подключением моей модели (Размер), поскольку она возвращает пустой массив.

Посмотреть скриншот моего Почтальона

Я уже использовал ref и populate для заполнения поля размера, но это не работает.

Коллекция размеров: Скриншот

Поделитесь, пожалуйста, схемой для Size модели.

Subha 28.06.2024 07:27

Метод populate Mongoose не поддерживает вложенные массивы напрямую.

Subha 28.06.2024 07:49

Я уже добавил модель размера.

das 28.06.2024 08:01

Я опубликовал свой ответ. Пожалуйста, проверьте и дайте мне знать ваш отзыв.

Subha 28.06.2024 08:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добавьте это в свою модель Product, удалив существующую variations.

variations: [
            {
            type: Schema.Types.ObjectId,
            ref: 'Size'
            }
        ]

Затем создайте Product вот так. Попробуйте использовать async((req,res) =>{.., поскольку мой код соответствует этому подходу.

const Products = require('./path_to_product_model');
const Size = require('./path_to_size_model');

//create "Size" Documents
 
const smallSize = new Size({ name: 'Small' });
const mediumSize = new Size({ name: 'Medium' });

await smallSize.save();
await mediumSize.save();

//create "Product" Document
 const newProduct = new Products ({
    name: req.body.name,
    imgURL: req.body.imgURL,
    description: req.body.description,
    categoryName: req.body.categoryName,
    isActive: req.body.isActive,
    price: req.body.price ,
    variations: [smallSize._id, mediumSize._id]
});

await newProduct.save();

Чтобы получить Product и заполнить его поле variations соответствующим Size documents, сделайте следующее:

const product = await Products.find({ isActive: true}).populate('variations');

Попробуйте это. Это сработает.

Для получения дополнительной информации о populate() вы можете перейти по ссылке на документ, приведенной ниже.

https://mongoosejs.com/docs/populate.html#saving-refs

N:B: - В приведенном выше блоке кода я использовал async-await для получения данных на основе Promise. Если вы хотите, вы можете измениться соответствующим образом.

Нужно ли мне добавлять размеры при создании продукта, даже если у меня уже есть коллекция размеров? Я приложил скриншот коллекции размеров.

das 28.06.2024 09:35

@das, Нет, вам не обязательно добавлять варианты Size при создании Product. Поле variations в Product schema представляет собой массив, и если вы не укажете никаких значений, по умолчанию это будет просто пустой массив. Работает ли приведенный выше код?

Subha 28.06.2024 09:41

Все равно не заполняется :(

das 28.06.2024 13:56

@das Хорошо, какую ошибку вы получаете? Вы внесли все соответствующие изменения?

Subha 28.06.2024 13:59

@das, есть ли данные (действительные идентификаторы ObjectId) в variations модели продукта, которые ссылаются на существующие документы размера? Если в variations модели продукта нет действительных ObjectIds, они не будут заполняться и будут возвращать нулевое значение, которое вы уже получаете

Subha 28.06.2024 14:04

@das вы также можете найти продукт по идентификатору и обновить его поле «варианты». Вы можете сделать это следующим образом const product = await Product.findByIdAndUpdate( productId, { $push: { variations: largeSize._id } }, { new: true } ).populate('variations');

Subha 28.06.2024 14:25

@das, я знаю, что застревать на этом целый день раздражает, но если у вас возникли проблемы с пониманием моего ответа, вы можете проверить эту ссылку, чтобы получить больше информации о том, как это работает. dev.to/paras594/how-to-use-populate-in-mongoose-node-js-mo0

Subha 28.06.2024 14:56

Теперь это работает. Спасибо за помощь @Subha :)

das 28.06.2024 15:09

@das , пожалуйста.Рада Вам помочь

Subha 28.06.2024 16:01

@das, пожалуйста, добавьте тег node к своему вопросу.

Subha 28.06.2024 16:03

Другие вопросы по теме