【问题标题】:Group by user in nested object mongoose在嵌套对象猫鼬中按用户分组
【发布时间】:2020-02-20 03:29:52
【问题描述】:

我想构建一个查询,它给我这样的输出

{
"idOfUser":[Array of missions],
"idOfUser":[Array of mission]
}

实际上是按计划中存在的用户对任务进行分组

每个用户都被分配了一项任务,并且为了进行规划,一个规划中可以有很多任务。

我已经做的是

if (data["date"]) {
            Planning.find({ start: { $eq: new Date(Number(data["date"])) } }).populate('mission').exec((err, doc) => {
                if (!err)
                    return response(res, doc)
                else
                    return throwError(err, 404, next)
            })
}

这给了我像

这样的输出
{ 
start:"some date",
end:"some date"
mission:[array of mission]
}

用户架构:

let UserSchema = new Schema({
    name: {
        type: Schema.Types.String,
        required: [true, "name must be required"],
    },
    email: {
        type: Schema.Types.String,
        required: [true, "email must be required"],
        unique: [true, "email already taken"],

    },
    password: {
        type: Schema.Types.String,
        required: true,
        validate: {
            validator: (pass) => pass.length >= 8,
            message: 'password must be consist of 8 characters'
        }
    },
    isAdmin: {
        type: Schema.Types.Boolean,
        default: false
    }
}); 

任务架构

let MissionSchema = new Schema({
    missionNotes: {
        type: Schema.Types.String,
        required: [true, "name is required"],
        // unique: [true, "must be unique"]
    },
    startDate: {
        type: Schema.Types.Date,
        required: [true, "startDate is required"],
    },
    endDate: {
        type: Schema.Types.Date,
        required: [true, "endDate is required"],

    },
    repeatInterval: {
        type: Schema.Types.Number,
        required: [true, "duration is required"],
    },
    pickupTime: {
        type: Schema.Types.Number,
        required: [true, "pickuptime is required"],
    },//minutes,
    flightNo: {
        type: Schema.Types.String,
        // required: [true, "flightNo is required"],
    },
    who: {
        type: Object,
        required: [true, "who is required"],
    },
    journey: {
        type: Object,
        required: [true, "journey is required"],
    },
    user: {
        type: Object,
        default: null
    },
    isAssign: {
        type: Schema.Types.Boolean,
        default: false,
    },
    info: {
        type: Schema.Types.String,
        // required: [true, "info is required"],
    },
    companyNotes: {
        type: Schema.Types.String
    },
    isCompleted: {
        type: Schema.Types.Boolean,
        default: false
    },
    car: {
        type: Object,
        default: null
    },
    fuel: {
        type: Schema.Types.Number,
        default: 0
    },
    extraExpense: {
        type: Schema.Types.Number,
        default: 0

    },
    crewInfo: {
        type: Schema.Types.String,
        default: ""
    },
    apt: {
        type: Schema.Types.String,
        default: ""
    },//actualpickuptime
    atad: {
        type: Schema.Types.String,
        default: ""
    },//actualtimeatdestination
    adt: {
        type: Schema.Types.String,
        default: ""
    },//actualdrivingtime
    acalpt: {
        type: Schema.Types.String,
        default: ""
    },//actualcalculatedpickuptime
    dap: {
        type: Schema.Types.String,
        default: ""
    },//delayafterpickup
    dacp: {
        type: Schema.Types.String,
        default: ""
    },//delayaftercalcpickup,
    isReminded: {
        type: Schema.Types.Boolean,
        default: false
    },

});

规划架构

let PlanningSchema = new Schema({
    title: {
        type: Schema.Types.String,
        // required: [true, "title is required"],
    },
    start: {
        type: Date,

        required: [true, "start is required"],
    },
    end: {
        type: Date,

        required: [true, "end is required"],

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


})

【问题讨论】:

    标签: mongodb express mongoose mongodb-query


    【解决方案1】:

    您可以通过MongoDB aggregation 实现此目的。 首先获取所有计划任务:

    // You have to be in an async function to await like this
    const plan = await Planning.find({ start: { $eq: new Date(Number(data["date"])) } });
    const plannedMission = [];
    plan.forEach(plan => { plannedMissions = [...plannedMissions, ...plan.mission] });
    
    /* The plannedMission array should be something like this:
     [ "missionId1", "missionId2", "missionId3"]
    */
    

    然后,我们按用户对任务进行分组,这就是聚合的用武之地:

    const pipeline = [ 
      { $match: { '_id': { $in: plannedMissions } } },
      { $group: { _id: "$user._id", missions: { $push: "$$ROOT"}  } }, 
    ];
    // You have to be in an async function to await like this
    const result = await db.missions.aggregate(pipeline);
    
    /* result is an array object like this:
      [ 
        { "_id" : userId1, "missions" : ['mission1', 'mission2'] },
        { "_id" : userId2, "missions" : ['mission1', 'mission2'] }
       ] 
    */
    
    // If you want to further reduce the result to just a single object, you can do this:
    const missionsByUser = {};
    
    result.forEach(res => userByMission[res._id] = res.missions);
    
    /* missionsByUser should be something like this:
      { 
        "userId1": ['mission1', 'mission2'],
        "userId2": ['mission1', 'mission2'] 
      }
    */
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      • 2014-02-10
      • 2014-07-13
      • 1970-01-01
      • 1970-01-01
      • 2017-02-12
      相关资源
      最近更新 更多