Search code examples
javascriptnode.jsexpressmongoose

i can't add new attribute in an object


I have a project in node and express and mongoose, i have a controller for return all orders of the logued client, when I query the database i want see the status of each order and depending on the state, add the availableStatus field to null or to the available states. this is my controller:

const getOrdersByUser = async ( req = request, res = response) => {
    try {
        const { id } = req.user;
        const orders = await Orders.find({ customer: id })
            .populate('status', 'name')
            .populate('account')
            .populate('package');

        if ( !orders ) {
            return res.status(200).json({
                ok: false,
                data: ['El usuario no tiene ordenes registradas!']
            })
        }

        const requestCancellation = await OrderStatus.findOne({ name: 'Solicitud de cancelación.'});
        
        orders.forEach(element => {
            if ( element.status.name === 'Carga en proceso.' || element.status.name === 'Carga en proceso(Demoras).') {
                console.log('entra aqui');
                element.availableStates = [requestCancellation]
            } else {
                element.availableStates = [null];
            }
        });

        console.log(orders[0].availableStates);
        console.log(orders);

        return res.status(200).json({
            ok: true,
            data: orders
        })

    } catch (error) {

        console.log(error);
        return res.status(400).json({
            ok: false,
            data: [error.message]
        })
    }

}

This is a response for console:

Server runing in port: 3005
Database Connected
entra aqui
[
  {
    _id: new ObjectId('65edfd1359cb75c67bdd4738'),
    name: 'Solicitud de cancelación.',
    description: 'El usuario desea cancelar la recarga, el administrador debe aprobar o no la cancelación.'
  }
]
[
  {
    _id: new ObjectId('65ede332942db9ca3807554c'),
    orden_number: 'Play',
    customer: new ObjectId('65cadbd69610d8bccb1168c7'),
    history: [ [Object], [Object] ],
    status: {
      _id: new ObjectId('65e86316940764700aa3a7b3'),
      name: 'Carga en proceso.'
    },
    account: {
      _id: new ObjectId('65cfc9279892a31557af028e'),
      game: new ObjectId('65ca524190a477fd6ec88b81'),
      access: 'Facebook',
      nickname: 'Prueba2',
      email: '[email protected]',
      user: new ObjectId('65cadbd69610d8bccb1168c7'),
      __v: 0
    },
    secure_codes: '111111 22222222 333333',
    package: {
      _id: new ObjectId('657b4f7815b946f9d46797cd'),
      amount: '7400'
    },
    comments: 'Se validara si el pago se realizo correctamente',
    create_at: 2024-03-10T16:43:30.862Z,
    update_at: 2024-03-12T04:03:47.849Z,
    __v: 1
  }
]

You can see that when I print the 'availableStatus' of the order in position 0, it shows me the content, but when I print the complete 'orders' object the 'availableStatus' attribute is not displayed in any of the orders. Likewise, when I make the request, the response does not bring 'availableStatus'

this is my response in postman from backend

{
    "ok": true,
    "data": [
        {
            "_id": "65ede332942db9ca3807554c",
            "orden_number": "Play",
            "customer": "65cadbd69610d8bccb1168c7",
            "history": [
                {
                    "status": "65e495b6e66f7303fe97f237",
                    "name_status": "Pago en Verificación",
                    "update_at": "2024-03-10T16:43:30.756Z",
                    "updater": "65cadbd69610d8bccb1168c7"
                },
                {
                    "status": "65e86316940764700aa3a7b3",
                    "name_status": "Carga en proceso.",
                    "update_at": "2024-03-12T04:03:47.847Z",
                    "updater": "65cadbd69610d8bccb1168c7"
                }
            ],
            "status": {
                "_id": "65e86316940764700aa3a7b3",
                "name": "Carga en proceso."
            },
            "account": {
                "_id": "65cfc9279892a31557af028e",
                "game": "65ca524190a477fd6ec88b81",
                "access": "Facebook",
                "nickname": "Prueba2",
                "email": "[email protected]",
                "user": "65cadbd69610d8bccb1168c7",
                "__v": 0
            },
            "secure_codes": "111111 22222222 333333",
            "package": {
                "_id": "657b4f7815b946f9d46797cd",
                "amount": "7400"
            },
            "comments": "Se validara si el pago se realizo correctamente",
            "create_at": "2024-03-10T16:43:30.862Z",
            "update_at": "2024-03-12T04:03:47.849Z",
            "__v": 1
        },
        {
            "_id": "65f199ccd9964955954877c4",
            "orden_number": "Play",
            "customer": "65cadbd69610d8bccb1168c7",
            "history": [
                {
                    "status": "65e495b6e66f7303fe97f237",
                    "name_status": "Pago en Verificación.",
                    "update_at": "2024-03-13T12:19:23.981Z",
                    "updater": "65cadbd69610d8bccb1168c7"
                }
            ],
            "status": {
                "_id": "65e495b6e66f7303fe97f237",
                "name": "Pago en Verificación."
            },
            "account": {
                "_id": "65cae9382a687ed2764e1a97",
                "game": "65ca524190a477fd6ec88b81",
                "access": "Activision",
                "nickname": "Clyde",
                "email": "[email protected]",
                "user": "65cadbd69610d8bccb1168c7",
                "__v": 0
            },
            "secure_codes": null,
            "package": {
                "_id": "657b4f7815b946f9d46797cd",
                "amount": "7400"
            },
            "comments": "Se validara si el pago se realizo correctamente",
            "create_at": "2024-03-13T12:19:24.081Z",
            "update_at": "2024-03-13T12:19:24.081Z",
            "__v": 0
        },
        {
            "_id": "65f1b1b58d54976da39f5f38",
            "orden_number": "Play",
            "customer": "65cadbd69610d8bccb1168c7",
            "history": [
                {
                    "status": "65e495b6e66f7303fe97f237",
                    "name_status": "Pago en Verificación.",
                    "update_at": "2024-03-13T14:01:25.679Z",
                    "updater": "65cadbd69610d8bccb1168c7"
                }
            ],
            "status": {
                "_id": "65e495b6e66f7303fe97f237",
                "name": "Pago en Verificación."
            },
            "account": {
                "_id": "65cae9382a687ed2764e1a97",
                "game": "65ca524190a477fd6ec88b81",
                "access": "Activision",
                "nickname": "Clyde",
                "email": "[email protected]",
                "user": "65cadbd69610d8bccb1168c7",
                "__v": 0
            },
            "secure_codes": null,
            "package": {
                "_id": "657b4f7815b946f9d46797cd",
                "amount": "7400"
            },
            "comments": "Se validara si el pago se realizo correctamente",
            "create_at": "2024-03-13T14:01:25.780Z",
            "update_at": "2024-03-13T14:01:25.780Z",
            "__v": 0
        }
    ]
}

really i don't understand what happend with the attribute 'availableStatus', why when i print availableStatus in console of a specify order this exist, but when i print the complet information of an order the attribute 'availableStatus' not exist?


Solution

  • Hmmm, it seems like a Mongoose problem.

    When you fetch/get data from the Database through the Mongoose, it's not returned the plain JavaScript Object; they are instances of the Mongoose Document class. This class has its own behavior on parse its data to object or etc.

    When you assign a property to this object (in this case is element.availableStates), it doesn't become a part of the Document's data but a JavaScript object property (this is why you can access it via orders[0].availableStates). So, when it comes to console.log(orders), the truly behavior is it converts its own data (Document) and shows them up. That why you can't see the data after modified it.

    How to fix this:

    1. Add the availableStates property to the Schema
    2. Convert the Document --> the plain JavaScipt object

    Example 1: Using forEach()

    orders.forEach(element => {
      element = element.toObject()
      if ( element.status.name === 'A' || element.status.name === 'B') {
        element.availableStates = [requestCancellation]
      } else {
        element.availableStates = [null];
      }
    });
    
    

    Example 2: Using map()

    const modifiedOrders = orders.map(order => {
      const plainOrder = order.toObject()
      if ( plainOrder.status.name === 'A' || plainOrder.status.name === 'B') {
        plainOrder.availableStates = [requestCancellation]
      } else {
        plainOrder.availableStates = [null];
      }
      return plainOrder;
    });