Mongoose是否可以在一个查询中查询文档并创建不存在的新文档?

时间:2019-03-04 19:35:47

标签: mongodb mongoose mongoose-schema

我试图弄清楚如何在MongoDB中更新集合。基本上,我想列出一个电子邮件地址,检查它们是否存在于数据库中,如果不存在,则从它们中创建一个新用户,所有这些都在同一查询中。这可能吗?

现在我正在这样做:

const usersWithEmailsOnly = [<array-of-emails];

User.update({
   email: {
      $in: usersWithEmailsOnly.map(userWithEmail => userWithEmail.email),
   },
}, { multi: true, upsert: true }).exec()

然后我从服务器获得以下响应:

{ ok: 0, n: 0, nModified: 0 }

当我查看数据库时,看到没有创建用户。还有什么我需要做的吗?

1 个答案:

答案 0 :(得分:2)

您要bulkWrite()

Users.bulkWrite(
  usersWithEmailsOnly.map(userWithEmail =>
    ({ 
      "updateOne": {
        "filter": { "email": userWithEmail.email },
        "update": { "$setOnInsert": { "name": userWithEmail.name } },
        "upsert": true
      }
    })
  )
)

这与$setOnInsert更新运算符结合使用,后者具有特殊条件:只有实际的“ upsert / insert” 发生时,指定的参数才 更新文档。因此,当匹配的现有文档是唯一使用的运算符时,它根本不会接受任何更改。

请注意,“ upserts” 将始终应用update语句的 query / predicate 部分中使用的条件,只要该表达式等于单数即可;即age: { $gt: 3 }不会是单数。对于大多数“数据加载” ,您通常希望创建一个静态谓词作为“唯一键” ,因此需要选择更新以及 some 其他数据,您可以根据需要在其中应用$setOnInsert

从技术上讲,它仍然是多个更新,但是与尝试循环代码中的一系列更新不同,这是与服务器之间的单个请求和响应。从应用程序的角度来看,它几乎具有与单个写入相同的响应速度(当然还有有效负载开销)。

没有真正的“单个语句” 这样的东西,因为不同的数据更新标准无法应用于MongoDB更新中的多个文档。您可以应用相同数据来更新多个文档,但是当您希望“此条件与文档匹配时,则意味着我会在发生这种情况时使用此特定数据进行更新” ,那就是您使用bulkWrite()的目的。