Mongoose - Как заполнить вложенный документ при условии - PullRequest
0 голосов
/ 06 сентября 2018

Я новичок в мангусте, я не знаю, как заселить при условии. Итак, это моя модель:

const OrderSchema = new Schema({
    products: [{ type: Schema.Types.ObjectId, ref: 'Product' }],
    remarks: {type: String, lowercase: true}
});
mongoose.model("Order", OrderSchema);


const ProductSchema = new Schema({
   reference: {type: String}
   status: {type: Schema.Types.ObjectId, ref: 'ProductStatus'}
});
mongoose.model("Product", ProductSchema);

const ProductStatus = new Schema({
    name: {type: String}
});

const CountrySchema = new Schema({
    name: {type: String}
});
mongoose.model("Country", CountrySchema);

У меня есть getOrderById методы

export const getOrderById = async (req, res) => {
let id = req.params.id;
try {
    await orderModel
        .findById(id)
        .populate({
            path: 'products',
            populate: {
              path: 'country',
              model: 'Country'
            }
         })
         .populate({
            path: 'products',
            populate: {
              path: 'status',
              model: 'ProductStatus'
            }
         })
        .exec(function (err, orders) {
            if (err) {
                res.send(err);
            }
            res.status(200).json(orders);
        });
} catch (error) {
    console.log(error);
}
}

А теперь я хотел бы показать в списке заказов все товары, которые имеют статус Получено во Франции.

1 Ответ

0 голосов
/ 07 сентября 2018

Во-первых, я полагаю, вы также пропустили ссылку на страну в схеме продукта, поэтому предположим, что это ваши исправленные схемы:

const OrderSchema = new Schema({
    products: [{
        type: Schema.Types.ObjectId,
        ref: 'Product'
    }],
    remarks: {
        type: String,
        lowercase: true
    }
});
const Order = mongoose.model("Order", OrderSchema);


const ProductSchema = new Schema({
    reference: {
        type: String
    },
    country: {
        type: Schema.Types.ObjectId,
        ref: 'Country'
    },
    status: {
        type: Schema.Types.ObjectId,
        ref: 'ProductStatus'
    }
});
const Product = mongoose.model("Product", ProductSchema);

const ProductStatusSchema = new Schema({
    name: {
        type: String
    }
});
const ProductStatus = mongoose.model("ProductStatus", ProductStatusSchema);

const CountrySchema = new Schema({
    name: {
        type: String
    }
});
const Country = mongoose.model("Country", CountrySchema);

Насколько я понимаю, вы хотите показывать только те товары, название страны которых - "Франция", а название продукта ProductStatus - "Получено", такие операции выполняются через Агрегирование

Ваш запрос может выглядеть следующим образом, если вы хотите выполнить один запрос:

const getOrderById = async (req, res) => {
        let id = req.params.id.toString();
        const ObjectId = mongoose.Types.ObjectId
        try {
            const aggregationStages = [{
                $match: {
                    _id: ObjectId(id) //It is important to cast to ObjectId in aggregations
                }
            }, {
                $lookup: {
                    from: 'products',
                    let: {
                        productIds: '$products'
                    },
                    pipeline: [{
                        $match: {
                            $expr: {
                                $in: ['$_id', '$$productIds']
                            }
                        }
                    }, {
                        $lookup: {
                            from: 'countries',
                            localField: 'country',
                            foreignField: '_id',
                            as: 'country'
                        }
                    }, {
                        $lookup: {
                            from: 'productstatuses',
                            localField: 'status',
                            foreignField: '_id',
                            as: 'status'
                        }
                    }, {
                        $match: {
                            'country.name': 'France',
                            'status.name': 'Received'
                        }
                    }],
                    as: 'products'
                }
            }];
            await orderModel.aggregate(aggregationStages)
                .exec(function (err, orders) { // The return is an array btw.
                    if (err) {
                        res.send(err);
                    }
                    res.status(200).json(orders);
                });
        } catch (error) {
            console.log(error);
        }
    }

Если вы чувствуете, что агрегация сложная, вы можете прибегнуть к разбивке на более простые запросы меньшего размера. Не стесняйтесь спрашивать, если вам нужно больше объяснений / изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...