【问题标题】:MongoDB Mongoose save or update with arrayMongoDB Mongoose 使用数组保存或更新
【发布时间】:2016-03-24 00:20:20
【问题描述】:

当用户保存问题时,问题可以包含“标签”数组。我想获取该标签数组并检查它们是否存在于标签集合中。如果标签存在,则更新计数,如果不存在,则将其添加到集合中。我编写了代码来执行此操作,但它似乎非常冗长。有没有更好/更简单/更简洁的方法来用 mongo/mongoose 做到这一点?该功能有点类似于堆栈溢出如何使用它的标记。

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"});
                })
            }
        })
    }
});

【问题讨论】:

    标签: javascript node.js mongodb express mongoose


    【解决方案1】:

    在 Mongoose API 中使用 find()stream() 时,您可以使用 MongoDB $in 运算符表达式。 find() 返回一个 Query 对象,然后可以使用该对象创建一个 QueryStream(它实现了 Node.js 的 ReadableStream 接口)。然后您可以使用.on 来处理每个流事件。

    请注意,您不能在 $in 表达式中使用 $regex 运算符表达式,因此在将数组传递给 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"});
                    });
                }
            });
        });
    

    【讨论】:

    • 这不太行……QuestionTags.find 中的所有内容都不再适用,因为它不再位于 forEach 中。如果tagsRegExp 包含 6 个标签,其中 5 个存在于集合中,那么您将在查询响应中取回这 5 个标签。这无助于为不存在的东西创建新标签。
    • @erichardson30 我已经在 find() 返回的 Query 对象上使用 Mongoose QueryStream 更新了代码和解释。
    • 这不会将任何内容保存到 questionTags 集合中
    • 你能发布一些示例数据吗?
    • 标签数据超级简单直接。它只是一个字符串数组 ["Java", "javascript", "agile"]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 2022-01-22
    • 2023-04-10
    • 2016-12-11
    • 2020-10-22
    • 2016-04-16
    相关资源
    最近更新 更多