使用 mongoose 将多个不存在的文档插入 MongoDB
Posted
技术标签:
【中文标题】使用 mongoose 将多个不存在的文档插入 MongoDB【英文标题】:Insert multiple none-existed documents to MongoDB using mongoose 【发布时间】: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
);
【问题讨论】:
【参考方案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
【讨论】:
***.com/questions/23803743/… 我在 github 上阅读了这篇文章和其他一些文章。他们唯一注意到的危害是我处理它们的未处理错误(如您在代码中所见)。我也觉得没那么复杂。它只是一个承诺,它在其他一些承诺(可能由 api 提供)处理程序的上下文中解析为一个值。请告诉我它是反模式的主要原因是什么? 好吧,您可以将 promise 链接起来,使其更具可读性。实际上,这与我上面的代码完全相同相同,只是多几行:) 使用您的代码如何将每个创建(或增加)的文档的 ID 推送到一个空数组?Promise.all(tags.map(findOrIncrease))
以上是关于使用 mongoose 将多个不存在的文档插入 MongoDB的主要内容,如果未能解决你的问题,请参考以下文章
使用 mongoose 一次将多个 ObjectId 插入子文档
链接多个 Promise,使用 map 循环数组并创建 mongoose 文档?