首页 > 解决方案 > 根据对象中的值使用不同的步骤

问题描述

使用 Mongoose,我创建了三个模型,一个称为movements,两个子模型称为inMovementand outMovement

const movementSchema = new Schema({
    actualState: {
        type: Schema.Types.ObjectID,
        ref: 'statemovements'
    },
    movementDate: {
        type: Date,
        required: true
    },
    business: {
        type: Schema.Types.ObjectID,
        ref: 'business',
        required: true
    },
    inspectors: [{
        type: String
    }],
    transport: {
        type: Schema.Types.ObjectID,
        ref: 'transports'
    },
    estimatedTime: Number,
    employees: Number,
    manHours: Number,
    filesLocations: [{ type: String }],
    dock: Boolean,
    door: Number
},{
    timestamps: true,
    discriminatorKey: '__type'
});
const inMovementSchema = new Schema({
    productsList: [{
        product: {
            type: Schema.Types.ObjectID,
            ref: 'products'
        },
        packages: Number,
        weight: Number,
        disposition: Boolean
    }]
});
const outMovementSchema = new Schema({
    productsList: [{
        product: {
            type: Schema.Types.ObjectID,
            ref: 'products'
        },
        exporter: {
            type: Schema.Types.ObjectID,
            ref: 'business'
        },
        importer: {
            type: Schema.Types.ObjectID,
            ref: 'business'
        },
        packages: Number,
        weight: Number,
        disposition: Boolean,
        labeled: {
            type: Schema.Types.ObjectID,
            ref: 'labels'
        }
    }],
    booking: String,
    thermograph: {
        type: Schema.Types.ObjectID,
        ref: 'thermographs'
    },
    photographic: Boolean,
    hasStock: Boolean,
    isExport: Boolean,
    internalDestination: {
        type: Schema.Types.ObjectID,
        ref: 'establishments'
    },
    externalDestination: {
        type: Schema.Types.ObjectID,
        ref: 'countries'
    }
});

最终结果是一个movements包含文档的集合,其中包含一个名为的值,该值__type可以是inMovementsoutMovements。在此之后,我为每个模型制作了三个不同的控制器,一个只请求inMovements,另一个只请求outMovements,最后一个movements用于两种类型的文档(除了模型之外,它们在三个中是相同的)。

movementsCTRL.getMixedMovements = async (req, res) => {
    let skip = 0;
    let limit = 10;
    let sort = { _id: 'asc' };
    let search = {};

    if (req.params.first != undefined && req.params.rows != undefined) {
        skip = filterFunc.calculateSkip(req.params.first);
        limit = filterFunc.calculateLimit(req.params.rows);
    }

    if (req.params.search != undefined) {
        search = filterFunc.calculateSearch(req.params.search);
    }

    if (req.params.sort != undefined) {
        sort = filterFunc.calculateSort(req.params.sort);
    }

    movementsModel
        .aggregate(pipelines.movementAggregate)
        .match(search)
        .sort(sort)
        .skip(skip)
        .limit(limit)
        .exec((err, ret) => {
            if (err) {
                res.status(500).json({ message: err.message });
            }
            else {
                movementsModel.countDocuments(search, (err, count) => {
                    if (err) {
                        res.status(500).json({ message: err.message });
                    }
                    else {
                        res.json({ count: count, values: ret });
                    }
                });
            };
        });
}

现在,我需要为每个模型制作管道,inMovements并为outMovements. 管道的数组保存在另一个类中,因此我可以在任何地方调用我需要的管道。

pipelines.inmovementAggregate = [
    {
        "$lookup": {
            from: 'transports',
            localField: 'transport',
            foreignField: '_id',
            as: 'transport'
        }
    }, {
        "$unwind": {
            "path": '$transport',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$addFields": {
            "products_id": {
                "$reduce": {
                    "input": "$productsList",
                    "initialValue": [],
                    "in": "$$this.product"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'products',
            localField: 'products_id',
            foreignField: '_id',
            as: 'products_id'
        }
    }, {
        "$addFields": {
            "productsList": {
                "$map": {
                    "input": "$productsList",
                    "as": "productList",
                    "in": {
                        "$mergeObjects": [
                            "$$productList",
                            {
                                "product": {
                                    "$arrayElemAt": [
                                        "$products_id",
                                        { "$indexOfArray": ["$products_id", "$$productList.product"] }
                                    ]
                                }
                            }
                        ]
                    }
                }
            }
        }
    }, {
        "$project": { "products_id": 0 }
    }, {
        "$lookup": {
            from: 'businesses',
            localField: 'business',
            foreignField: '_id',
            as: 'business'
        }
    }, {
        "$unwind": {
            "path":'$business',
            "preserveNullAndEmptyArrays":true
        }
    },{
        "$lookup": {
            from: 'countries',
            localField: 'business.country',
            foreignField: '_id',
            as: 'business.country'
        }
    }, {
        "$unwind": {
            "path": '$business.country',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'statemovements',
            localField: 'actualState',
            foreignField: '_id',
            as: 'actualState'
        }
    }, {
        "$unwind": {
            "path": '$actualState',
            "preserveNullAndEmptyArrays":true
        }
    }
]
pipelines.outmovementAggregate = [
    {
        "$lookup": {
            from: 'transports',
            localField: 'transport',
            foreignField: '_id',
            as: 'transport'
        }
    }, {
        "$unwind": {
            "path":'$transport',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$addFields": {
            "products_id": {
                "$reduce": {
                    "input": "$productsList",
                    "initialValue": [],
                    "in": "$$this.product"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'products',
            localField: 'products_id',
            foreignField: '_id',
            as: 'products_id'
        }
    }, {
        "$addFields": {
            "exporters_id": {
                "$reduce": {
                    "input": "$productsList",
                    "initialValue": [],
                    "in": "$$this.exporter"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'businesses',
            localField: 'exporters_id',
            foreignField: '_id',
            as: 'exporters_id'
        }
    }, {
        "$addFields": {
            "countries_id": {
                "$reduce": {
                    "input": "$exporters_id",
                    "initialValue": [],
                    "in": "$$this.country"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'countries',
            localField: 'countries_id',
            foreignField: '_id',
            as: 'countries_id'
        }
    }, {
        "$addFields": {
            "exporters_id": {
                "$map": {
                    "input": '$exporters_id',
                    "as": "businessE",
                    "in": {
                        "$mergeObjects": [
                            "$$businessE",
                            {
                                "country": {
                                    "$arrayElemAt": [
                                        "$countries_id",
                                        { "$indexOfArray": ["$countries_id", "$$businessE.country"] }
                                    ]
                                }
                            }
                        ]
                    }
                }
            }
        }
    }, {
        "$addFields": {
            "importers_id": {
                "$reduce": {
                    "input": "$productsList",
                    "initialValue": [],
                    "in": "$$this.importer"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'businesses',
            localField: 'importers_id',
            foreignField: '_id',
            as: 'importers_id'
        }
    }, {
        "$addFields": {
            "countries_id": {
                "$reduce": {
                    "input": "$importers_id",
                    "initialValue": [],
                    "in": "$$this.country"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'countries',
            localField: 'countries_id',
            foreignField: '_id',
            as: 'countries_id'
        }
    }, {
        "$addFields": {
            "importers_id": {
                "$map": {
                    "input": '$importers_id',
                    "as": "businessI",
                    "in": {
                        "$mergeObjects": [
                            "$$businessI",
                            {
                                "country": {
                                    "$arrayElemAt": [
                                        "$countries_id",
                                        { "$indexOfArray": ["$countries_id", "$$businessI.country"] }
                                    ]
                                }
                            }
                        ]
                    }
                }
            }
        }
    }, {
        "$addFields": {
            "labels_id": {
                "$reduce": {
                    "input": "$productsList",
                    "initialValue": [],
                    "in": "$$this.labeled"
                }
            }
        }
    }, {
        "$lookup": {
            from: 'labels',
            localField: 'labels_id',
            foreignField: '_id',
            as: 'labels_id'
        }
    }, {
        "$addFields": {
            "productsList": {
                "$map": {
                    "input": "$productsList",
                    "as": "productList",
                    "in": {
                        "$mergeObjects": [
                            "$$productList",
                            {
                                "product": {
                                    "$arrayElemAt": [
                                        "$products_id",
                                        { "$indexOfArray": ["$products_id", "$$productList.product"] }
                                    ]
                                }
                            },
                            {
                                "exporter": {
                                    "$arrayElemAt": [
                                        "$exporters_id",
                                        { "$indexOfArray": ["$exporters_id", "$$productList.exporter"] }
                                    ]
                                }
                            },
                            {
                                "importer": {
                                    "$arrayElemAt": [
                                        "$importers_id",
                                        { "$indexOfArray": ["$importers_id", "$$productList.importer"] }
                                    ]
                                }
                            },
                            {
                                "labeled": {
                                    "$arrayElemAt": [
                                        "$labels_id",
                                        { "$indexOfArray": ["$labels_id", "$$productList.labeled"] }
                                    ]
                                }
                            }
                        ]
                    }
                }
            }
        }
    }, {
        "$project": { "products_id": 0, "exporters_id": 0, "importers_id": 0, "labels_id": 0, "countries_id": 0 }
    }, {
        "$lookup": {
            from: 'businesses',
            localField: 'business',
            foreignField: '_id',
            as: 'business'
        }
    }, {
        "$unwind": {
            "path":'$business',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'countries',
            localField: 'business.country',
            foreignField: '_id',
            as: 'business.country'
        }
    }, {
        "$unwind": {
            "path":'$business.country',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'statemovements',
            localField: 'actualState',
            foreignField: '_id',
            as: 'actualState'
        }
    }, {
        "$unwind": {
            "path":'$actualState',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'thermographs',
            localField: 'thermograph',
            foreignField: '_id',
            as: 'thermograph'
        }
    }, {
        "$unwind": {
            "path":'$thermograph',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'businesses',
            localField: 'internalDestination',
            foreignField: '_id',
            as: 'internalDestination'
        }
    }, {
        "$unwind": {
            "path":'$internalDestination',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'countries',
            localField: 'internalDestination.country',
            foreignField: '_id',
            as: 'internalDestination.country'
        }
    }, {
        "$unwind": {
            "path":'$internalDestination.country',
            "preserveNullAndEmptyArrays":true
        }
    }, {
        "$lookup": {
            from: 'countries',
            localField: 'externalDestination',
            foreignField: '_id',
            as: 'externalDestination'
        }
    }, {
        "$unwind": {
            "path":'$externalDestination',
            "preserveNullAndEmptyArrays":true
        }
    }
]

现在,问题是我无法为movements. 我完成这项工作的唯一方法是放置outMovements管道,但它会在对象中产生不必要的步骤,如果不存在则inMovement留下一个空白。internalDestination我一直无法找到一种方法来区分不同的文档并使用正确的管道。

标签: mongodbmongoosemongodb-queryaggregation-framework

解决方案


推荐阅读