简体   繁体   中英

MongoDB Mongoose save or update with array

When a user saves a question, the question can contain an array of "tags". I want to take that array of tags and check to see if they exist in the tag collection. If the tags exist, update the count, if not, add it to the collection. I have code written to do this but it seems very verbose. Is there a better/easier/more concise way to do this with mongo/mongoose? The functionality is kind of similar to how stack overflow works with it's tagging.

apiRouter.post('/', function(req, res) {
    var question = new Questions();

    question.text = req.body.text;
    question.answers = req.body.answers;
    question.tech = req.body.tech;
    question.tags = req.body.tags;
    question.level = req.body.level;
    question.createdAt = req.body.createdAt;

    question.save(function(err, questions) {
        if(err) res.send(err);
        res.json({message: "Question was created."});
    });

    for each(tag in req.body.tags) {
        QuestionTags.find({ 'tag': { $regex: new RegExp(tag, "i") } }, function(err, tags) {
            if(err) res.send(err);
            if(tags.length === 0) {
                var tagObj = new QuestionTags();
                tagObj = {
                    tag: tag,
                    count: 0
                }
                tagObj.save(function(err, questions) {
                    if(err) res.send(err);
                    res.json({message: "Tag created"});
                });
            } else {
                var tagObj = new QuestionTags();
                tagObj = tags;

                tagObj.count++;

                tagObj.save(function(err, questions) {
                    if(err) res.send(err);
                    res.json({message: "Tag updated"});
                })
            }
        })
    }
});

You can use the MongoDB $in operator expression when using find() with stream() from the Mongoose API. find() returns a Query object which can then be used to create a QueryStream (which implements the Node.js ReadableStream interface). You can then use .on to handle each stream event.

Note that you cannot use $regex operator expression inside of an $in expression, so you will have to take care of that before passing the array into find() .

apiRouter.post('/', function(req, res) {
    var question = new Questions();

    question.text = req.body.text;
    question.answers = req.body.answers;
    question.tech = req.body.tech;
    question.tags = req.body.tags;
    question.level = req.body.level;
    question.createdAt = req.body.createdAt;

    question.save(function(err, questions) {
        if(err) res.send(err);
        res.json({message: "Question was created."});
    });

    var tagsRegExp = [];

    req.body.tags.forEach(function(tag) {
        tagsRegExp.push(new RegExp(tag, "i");
    }

    QuestionTags.find({ 'tag': { $in : tagsRegExp }}).stream()
        .on('error', function(err) {
            res.send(err);
        }).on('data', function(tag) {
            if(tag.length === 0) {
                var tagObj = new QuestionTags();
                tagObj = {
                    tag: tag,
                    count: 0
                }
                tagObj.save(function(err, questions) {
                    if(err) res.send(err);
                    res.json({message: "Tag created"});
                });
            } else {
                var tagObj = new QuestionTags();
                tagObj = tag;

                tagObj.count++;

                tagObj.save(function(err, questions) {
                    if(err) res.send(err);
                    res.json({message: "Tag updated"});
                });
            }
        });
    });

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