Home > Back-end >  How can I $push an item in two different fields, depending on the condition?
How can I $push an item in two different fields, depending on the condition?

Time:06-07

I'm trying to receive the user location and store it in the database. Also, the user can choose if he wants to save all his previous locations or not. So I have created a boolean variable historicEnable: true/false. So when the historicEnable is true, I want to push to historicLocation[] array in the UserSchema and if it is false, I want just to update currentLocation[] array in the UserSchema.

conntrollers/auth.js

exports.addLocation = asyncHandler(async (req, res, next) => {
  const {phone, location, status, historicEnable} = req.body;
  let theLocation;
  
  if (historicEnable== true){
    theLocation = await User.findOneAndUpdate(
      { phone },
      { $push:{ locationHistoric: location, statusHistoric: status }},
      { new: true }
    )
  } else if(historicEnable== false){
    theLocation = await User.findOneAndUpdate(
      { phone },
      { location, status },
      { new: true }
    )
  }

  res.status(200).json({
      success: true,
      msg: "A location as been created",
      data: theLocation,
      locationHistory: locationHistory
  })
})

models/User.js

...
  currentLocation: [
    {
      location: {
        latitude: {type:Number},
        longitude: {type:Number},
      },

      status: {
        type: String
      },
    
      createdAt: {
        type: Date,
        default: Date.now,
      }
    }
  ],

  historicLocation: [
    {
      locationHistoric: {
        latitude: {type:Number},
        longitude: {type:Number},
      },

      statusHistoric: {
        type: String
      },
    
      createdAt: {
        type: Date,
        default: Date.now,
      }
    }
  ]

Also, not sure how to make the request body so the function works.

req.body

{
  "phone": " 1234",
  "historicEnable": true,
  "loications": [
    {
      "location": {
        "latitude": 25,
        "longitude": 35
      },
      "status": "safe"
    }
  ]
}

To sum up, if historicEnable is true, the data will be pushed in historicLocation, and if it false, to update the currentLocation.

How can I solve this?

CodePudding user response:

You can use an update with an aggregation pipeline. If the historicEnable is known only on db level:

db.collection.update(
  {phone: " 1234"},
  [
    {$addFields: {
      location: [{location: {latitude: 25, longitude: 35}, status: "safe"}]
    }
  },
  {
    $set: {
      historicLocation: {
        $cond: [
          {$eq: ["$historicEnable", true]},
          {$concatArrays: ["$historicLocation", "$location"]},
          "$historicLocation"
        ]
      },
      currentLocation: {
        $cond: [
          {$eq: ["$currentLocation", false]},
          {$concatArrays: ["$currentLocation", "$location"]},
          "$currentLocation"
        ]
      }
    }
  },
  {
    $unset: "location"
  }
])

See how it works on the playground example

If historicEnable is known from the input, you can do something like:

exports.addLocation = asyncHandler(async (req, res, next) => {
  const phone = req.body.phone
  const historicEnable= req.body.historicEnable
  const locObj = req.body.location.locationHistoric[0];
  locObj.createdAt = req.body.createdAt
  const updateQuery = historicEnable ? { $push:{ locationHistoric: locObj}} : { $push:{ currentLocation: locObj}};


  const theLocation = await User.findOneAndUpdate(
      { phone },
      updateQuery,
      { new: true }
    )
  

  res.status(200).json({
      success: true,
      msg: "A location as been created",
      data: theLocation,
      locationHistory: locationHistory
  })
})
  • Related