简体   繁体   中英

Mongoose won't update sub-document

I've been banging my head against this for a few hours now and just can't seem to figure it out. I decided to use Mongo on a learning project to see how I like it. Mongoose came as the recommended way to use it, so I dove into that too. I have two schemas:

var PluginSchema = new Schema({
    name: { type: String, required: true },
    slug: { type: String },
    description: { type: String },
    created_date: { type: Date, default: Date.now },
    active: { type: Boolean, default: true },
    user: { type: Schema.Types.ObjectId, ref: 'User' },
    versions: [PluginVersion.schema]
});

PluginSchema.methods.getLatestVersion = function(callback) {
    if(this.versions.length > 0) {
        this.versions.sort(function(a, b) {
            if(semver.gt(a.version, b.version)) {
                return 1;
            } else if(semver.lt(a.version, b.version)) {
                return -1;
            } else {
                return 0;
            }
        });
        callback(this.versions[this.versions.length-1]);
    } else {
        callback(undefined);
    }
};

and

var PluginVersionSchema = new Schema({
    version: { type: String, required: true },
    downloads: { type: Number, default: 0 },
    size: { type: Number, required: true },
    updatedChecks: { type: Number, default: 0 },
    fileName: { type: String, required: true },
    uploadedDate: { type: Date, default: Date.now }
});

The issue here is the 'versions' relationship. At some point I want to update a version of the Plugin. The thing I want to update is the updatedChecks field. Basically just updatedChecks += 1 .

Plugin.findById(req.params.plugin_id)
    .populate('user')
    .populate('versions')
    .exec(function(err, plugin) {
        if(err) {
            res.status(404);
            res.send("Plugin not found.");
        } else {
            plugin.getLatestVersion(function(version) {
                if(version !== undefined) {
                    pluginData = {
                        stuff: "that",
                        gets: "returned",
                        tothe: "user"
                    };

                    // This says 'Affected: 1'.  As expected
                    PluginVersion.update({_id: version._id}, {
                        updatedChecks: version.updatedChecks + 1
                    }, function(err, affected) {
                        console.log("Affected: " + affected);
                        if(err) { res.send(err); }
                        res.status(200);
                        res.json(pluginData);
                    });
                } else {
                    res.status(404);
                    res.send("No versions found for this plugin.");
                }
            });
        }
    });

So far, so good. However, when I try to access that version again via the Plugin schema, the updatedChecks value hasn't changed! I checked the _id value on the version I'm updating versus the version that gets pulled from the Plugin.versions field and they are they same. Do I need to remove the version from Plugin.versions and re-insert a new one with the updated value? I also tried just updating the value and calling save() but that didn't seem to work either.

I ended up getting this work by accessing the plugin version directly from the Plugin object.

var pluginIndex = false;
for(var i = 0; i < plugin.versions.length; i++) {
    if(plugin.versions[i]._id === version._id) {
        pluginIndex = i;
    }
}

if(pluginIndex !== false) {
    plugin.versions[pluginIndex].updatedChecks++;
    plugin.versions[pluginIndex].markModified('updatedChecks');
    plugin.versions[pluginIndex].save(function() {
        plugin.markModified('versions');
        plugin.save(function() {
            res.status(200);
            res.json(pluginData);
        });
    });
}

I also has a little help from: Mongoose save() not updating value in an array in database document

The problem here is, your updating query is written wrong. It must be

PluginVersion.update({
    _id: version._id
}, {
    $set: {
        updatedChecks: version.updatedChecks + 1
    } 
}, function(...) {
    ...
});

or

PluginVersion.update({
    _id: version._id
}, {
    $inc: {
        updatedChecks: 1
    } 
}, function(...) {
    ...
});

You can find more update operators here: http://docs.mongodb.org/manual/reference/operator/update/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM