Search code examples
javascriptnode.jsmongodbexpressmongoose

Mongoose make a object with _id


i am working witn node js and express, i use mongoose for manage the database from backend, i have the nect model for a orden

const { Schema, model } = require('mongoose');

const orderSchema = Schema({
    orden_number: {
        type: String,
        required: true,
    },
    create_at: {
        type: Date,
        default: Date.now
    },
    update_at: {
        type: Date,
        default: Date.now
    },
    customer: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        require: true
    },
    history: [{
        status: {
            type: Schema.Types.ObjectId,
            ref: 'OrderStatus',
            required: true
        },
        name_status: { 
            type: String, 
            required: true
        },
        update_at: { 
            type: Date,
            required: true,
            default: Date.now
        },
        updater: {
            type: Schema.Types.ObjectId,
            ref: 'User',
            required: true
        }
    }],
    status: {
        type: Schema.Types.ObjectId,
        ref: 'OrderStatus',
        require: true
    },
    account: {
        type: Schema.Types.ObjectId,
        ref: 'Accounts',
        require: true
    },
    secure_codes: {
        type: String
    },  
    package: {
        type: Schema.Types.ObjectId,
        ref: 'Packages',
        require: true
    },
    comments: [ {comment: { type: String, required: true}}]

});

module.exports = model( 'Orders', orderSchema )

When i insert a register, automatically the array history create a _id for each object, if i edit a register and i want insert a new objet in the list 'history', this new register have a new _id, like in the next photo.

Here you can see the register in database

It's my post controller

const postOrder = async ( req = request, res = response ) => {
    try {
        const { accountId, codes, packageId } = req.body
        const customer = req.user.id;
        
        const infoAccount = await Accounts.findById( accountId );
        if ( !infoAccount ) throw new Error ('No existe esta cuenta en la base de datos.');
        if ( !infoAccount.user.equals(customer)) throw new Error('La cuenta a recargar no pertenece al usuario.');

        const defaultStatus = await OrderStatus.findOne({ name: 'Pago en Verificación'})
        if ( !defaultStatus ) throw new Error('No se pudo encontrar el estado para esta orden, valide con administrador!')

        const history = {
            status: defaultStatus._id,
            name_status: defaultStatus.name,
            update_at: Date.now(),
            updater: customer,
        }
        
        let secure_codes = null;
        if ( infoAccount.access === "Facebook") {
            if ( !codes ) throw new Error('Se requieren que envies los codigos ya que tu acceso es con facebook')
            secure_codes = codes;
        }
        
        const infoPackage = await Packages.findById( packageId );
        if ( !infoPackage ) throw new Error('Este paquete no existe en la base de datos')
        
        const orderData = {
            account         : infoAccount._id,
            comments        : 'Se validara si el pago se realizo correctamente',
            customer,
            history,
            orden_number    : 'Play',
            package         : infoPackage._id,
            secure_codes,
            status          : defaultStatus._id,
        }

        const order = await new Orders( orderData )
        order.save();

        return res.status(201).json({
            ok: true,
            data: ['Orden creada con exito.']
        })

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

And it's my put controller

const putStatusOrder = async ( req = request, res = response) => {
    try {
        const { id: orderId } = req.params;
        
        const order = await Orders.findById( orderId ).populate('status', 'name');
        if ( !order ) throw new Error('No existe la orden que se desea actualizar');

        const { status } = req.body

        const infoStatus = await OrderStatus.findById(status);
        if ( !infoStatus ) throw new Error('El estado que se quiere asignar no existe')

        const history = order.history;
        history.push({
            status,
            name_status: infoStatus.name,
            update_at: Date.now(),
            updater: req.user.id
        })
        order.history = history;
        order.save();
        
        return res.status(200).json({
            ok: true,
            data: order
        })
    } catch (error) {
        console.log(error);
        return res.status(400).json({
            ok: false,
            data: [error.message]
        })
    }

}

When i create or update a register i don't want a new id in each object of 'history', how can i do that? I don't want a subdocument, i only want a history for save the traceability of an order.


Solution

  • In mongoose, all top-level and subdocuments automatically have an _id assigned to them with a value of type ObjectId.

    In order to stop this feature you need to explicitly declare the _id: false option in the schema.

    For you that would be:

    const orderSchema = Schema({
    
        //..
        //...
        history: [{
            status: {
                type: Schema.Types.ObjectId,
                ref: 'OrderStatus',
                required: true
            },
            name_status: { 
                type: String, 
                required: true
            },
            update_at: { 
                type: Date,
                required: true,
                default: Date.now
            },
            updater: {
                type: Schema.Types.ObjectId,
                ref: 'User',
                required: true
            },
            _id: false //< declare this in the schema for history
        }],
        //...
        //...
    
    });