Search code examples
node.jsmongoosemongoose-schema

With Mongoose is there an efficient way to update the Model and add new key/values to previously saved documents?


Question: Once a Model has been created in Mongoose is there a way to update the Model and add the new key/values to documents that were previously saved?

In the example below documents containing dataName, data1, data2, data3 are stored in the DB. Later I updated the Model to include data4 and data5. All new documents were stored with the additional keys. However old documents didn't automatically get an empty data4 and data5. Other than doing it manually how would I add these keys to previously saved documents?

"use strict";

const bodyParser = require('body-parser');
const express = require('express');
const mongoose = require('mongoose');
const path = require('path');

const app = express();

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

const urlEncoded = bodyParser.urlencoded({ extended: true });

const WillThisExpandSchema = new mongoose.Schema({
    dataName: {
        type: String,
        required: true
    },
    data1: {
        type: String,
        required: true
    },
    data2: {
        type: String,
        required: true
    },
    data3: {
        type: String,
        required: true
    }
});

const WillThisExpand = mongoose.model('willThisExpand', WillThisExpandSchema);

app.get('/', (req, res)=> {
    res.render('index');
});

app.post('/upload', urlEncoded, async (req, res) => {

    let { dataName, data1, data2, data3 } = req.body;

    let newItem = new WillThisExpand({
        dataName, data1, data2, data3
    })

    await newItem.save();

    res.redirect('/');
});

let mongooseConnection = 'mongodb+srv://administrator:<password>@websites.tolyc.mongodb.net/mongooseTest?retryWrites=true&w=majority';

mongoose
    .connect(mongooseConnection, { autoIndex: false, useCreateIndex: true, useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false })
    .then(function () {
        console.log('mongoose connected');
    })
    .catch(function (error) {
        logErrorMessage(error);
    });

app.listen(8080, () => {
    console.log('app listening on port 8080');
})

Solution

  • There may be better ways to do this but I figured out an easy method that works.

    1. Update the Schema to reflect the new keys.
    2. Make a route, that uses .updateMany(). Include a regex that matches every single document. /(.*?)/g
    3. Hit the route with the browser and the keys are added.
    4. Delete the route.

    For example,

    app.get('/update', async (req, res) => {
    
        await WillThisExpand.updateMany({ dataName: /(.*?)/g }, { data4: '', data5: '' });
    
        res.redirect('/');
    
    });
    

    I tested this and it seems to work perfect. I could search by the new added keys and when I added values they returned without error and were usable.