【问题标题】:Insert multiple none-existed documents to MongoDB using mongoose使用 mongoose 将多个不存在的文档插入 MongoDB
【发布时间】:2018-09-20 12:38:14
【问题描述】:

我想保存多个文档,这些文档是在以井号“#”表示的帖子上找到的标签。我在数组中有标签。例如:

var tags = ['banana', 'apple', 'orange', 'pie']

我遍历它们并将它们转换为文档对象(以将它们插入数据库)。问题是我想将一个 new 文档插入到集合中,前提是它之前从未插入过。如果它在我想将插入文档的userCounter 属性增加一之前插入。

var tags = ['banana', 'apple', 'pie', 'orange'];

var docs = tags.map(function(tagTitle) {
  return {
    title: tagTitle,
    // useCounter: ??????????
  };
});

var Hashtag = require('./models/Hashtag');

/**
* it creates multiple documents even if a document already exists in the collection,
* I want to increment useCounter property of each document if they exist in the collection;
* not creating new ones.
* for example if a document with title ptoperty of 'banana' is inserted before, now increment
* document useCounter value by one. and if apple never inserted to collection, create a new document 
* with title of 'apple' and set '1' as its initial useCounter value
*/

Hashtag.create(docs)
.then(function(createdDocs) {

})
.then(null, function(err) {
  //handle errors
});

【问题讨论】:

    标签: javascript mongodb mongoose


    【解决方案1】:
    async function findOrIncrease(title) {      
       let hashtag = await Hashtag.findOne({title});
       if(hashtag) {
         hashtag.userCounter++;
       } else {
         hashtag = new Hashtag({title, userCounter: 1});
       }
       await hashtag.save();
     }
    

    可用作:

      (async function() {
        for(const title of tags)
          await findOrIncrease(title);
      })()
    

    或者如果你想并行执行:

      tags.forEach(findOrIncrease);
    

    您可以通过使用 mongodbs 索引来加快速度。

    【讨论】:

      【解决方案2】:

      感谢@Jonas W 的回复,我还找到了另一个解决方案。我认为基于标签数组做出一些承诺并从这些承诺中解析标签文档(或出于某些原因拒绝它们)可能会更好(因为它在性能方面更清晰、更快)。然后使用Promise.all() 做出提供猫鼬文档的完整承诺(根据某些条件创建或更新)。是这样的:

      // some other chains
      .then((xxxx) => {
              const hashtagsTitles = require('../../src/hashtags/hashtagParser').hashtags(req.newPost.caption);
              const Hashtag = require('../../src/database/models/Hashtag');
      
              let findOrIncrease = title =>
                  new Promise((resolve, reject) => {
                      Hashtag.findOne({
                              title
                          })
                          .then((hashtag) => {
                              if (!hashtag) {
                                  new Hashtag({
                                          title,
                                          usageCount: 0
                                      }).save()
                                      .then(hashtag => resolve(hashtag._id))
                                      .catch(err => reject(err));
                              } else {
                                  hashtag.usageCount++;
                                  hashtag.save()
                                      .then(hashtag => resolve(hashtag._id))
                                      .catch(err => reject(err));
                              }
                          })
                          .catch(err => reject(err));
                  });
      
              let promiseArr = hashtagsTitles.map((hashtagTitle) =>
                  findOrIncrease(hashtagTitle)
              );
      
              return Promise.all(promiseArr)
                  .then(results => results)
                  .catch(err => {
                      throw err
                  });
          })
          .then((hashtags) => {
              hashtags.forEach((hashtag) => req.newPost.hashtags.push(hashtag));
          })
          //there might be some other chains
      

      这里还有一个很好的指南: Mongoose - Create document if not exists, otherwise, update- return document in either case

      【讨论】:

      • 我在 github 上阅读了这篇文章和其他一些文章。他们唯一注意到的危害是我处理它们的未处理错误(如您在代码中所见)。我也觉得没那么复杂。它只是一个承诺,它在其他一些承诺(可能由 api 提供)处理程序的上下文中解析为一个值。请告诉我它是反模式的主要原因是什么?
      • 好吧,您可以将 promise 链接起来,使其更具可读性。实际上,这与我上面的代码完全相同相同,只是多几行:)
      • 使用您的代码如何将每个创建(或增加)的文档的 ID 推送到一个空数组?
      • Promise.all(tags.map(findOrIncrease))
      猜你喜欢
      • 2013-12-13
      • 1970-01-01
      • 2020-12-26
      • 2019-03-10
      • 2013-02-15
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 2012-05-18
      相关资源
      最近更新 更多