Mongoose:原子 FindOne-Or-Insert(),如果找到则不更新现有实例
Mongoose: atomic FindOne-Or-Insert(), do not update existing instance if found
在 Mongoose 中,我正在寻求以原子方式执行 Model.FindOne-Or-Insert()
,与当前可用的功能和签名类似 Model.FindOneAndUpdate()
,除非实例存在(即匹配 filter
)然后不要使用提供的 object
进行更新,而是按原样找到 return 实例,如果不存在(即与 filter
不匹配),则插入 object
和 return 新实例。
我找不到使用 Model.FindOneAndUpdate()
的方法,通过尝试对其 options
的差异而不向 object
提供不喜欢的字段来不对现有实例执行更新如果实例存在则更新。
所以,我当前的非原子 解决方法是Model.FindOne()
and if not found then perform Document.save()
。
const Foo = DB.model('foo', FooSchema)
async function findOneAndUpdateFoo(jsonFoo, next) {
const filter = {
deletedAt: null
}
if (jsonFoo.dsAccountId) {
filter.dsAccountId = jsonFoo.dsAccountId
}
if (jsonIntegration.dsUserId) {
filter.dsUserId = jsonIntegration.dsUserId
}
if (jsonFoo.providerId) {
filter.providerId = jsonFoo.providerId
}
const fooDoc = {
name: jsonFoo.name,
dsAccountId: jsonFoo.dsAccountId,
dsUserId: jsonFoo.dsUserId,
providerId: jsonFoo.providerId,
providerName: jsonFoo.providerName,
// Most of these fields could be empty
accessToken: jsonFoo.accessToken,
refreshToken: jsonFoo.refreshToken,
scope: jsonFoo.scope,
tokenType: jsonFoo.tokenType,
expiresAt: jsonFoo.expiresAt
}
return await Foo.findOneAndUpdate(
filter, // find a document with that filter
fooDoc, // document to insert when nothing was found
{ upsert: true, new: true, runValidators: true } // options
)
.catch(next)
}
建议?谢谢
您可以在更新参数中使用 $setOnInsert
,这样它就只适用于插入的情况;在文档已经存在的情况下,更新成为空操作:
return await Foo.findOneAndUpdate(
filter, // find a document with that filter
{$setOnInsert: fooDoc}, // document to insert when nothing was found
{ upsert: true, new: true, runValidators: true }
)
请注意,您还应该为 filter
中包含的字段创建唯一索引,然后处理重复错误的可能性。请参阅 了解详细原因。
在 Mongoose 中,我正在寻求以原子方式执行 Model.FindOne-Or-Insert()
,与当前可用的功能和签名类似 Model.FindOneAndUpdate()
,除非实例存在(即匹配 filter
)然后不要使用提供的 object
进行更新,而是按原样找到 return 实例,如果不存在(即与 filter
不匹配),则插入 object
和 return 新实例。
我找不到使用 Model.FindOneAndUpdate()
的方法,通过尝试对其 options
的差异而不向 object
提供不喜欢的字段来不对现有实例执行更新如果实例存在则更新。
所以,我当前的非原子 解决方法是Model.FindOne()
and if not found then perform Document.save()
。
const Foo = DB.model('foo', FooSchema)
async function findOneAndUpdateFoo(jsonFoo, next) {
const filter = {
deletedAt: null
}
if (jsonFoo.dsAccountId) {
filter.dsAccountId = jsonFoo.dsAccountId
}
if (jsonIntegration.dsUserId) {
filter.dsUserId = jsonIntegration.dsUserId
}
if (jsonFoo.providerId) {
filter.providerId = jsonFoo.providerId
}
const fooDoc = {
name: jsonFoo.name,
dsAccountId: jsonFoo.dsAccountId,
dsUserId: jsonFoo.dsUserId,
providerId: jsonFoo.providerId,
providerName: jsonFoo.providerName,
// Most of these fields could be empty
accessToken: jsonFoo.accessToken,
refreshToken: jsonFoo.refreshToken,
scope: jsonFoo.scope,
tokenType: jsonFoo.tokenType,
expiresAt: jsonFoo.expiresAt
}
return await Foo.findOneAndUpdate(
filter, // find a document with that filter
fooDoc, // document to insert when nothing was found
{ upsert: true, new: true, runValidators: true } // options
)
.catch(next)
}
建议?谢谢
您可以在更新参数中使用 $setOnInsert
,这样它就只适用于插入的情况;在文档已经存在的情况下,更新成为空操作:
return await Foo.findOneAndUpdate(
filter, // find a document with that filter
{$setOnInsert: fooDoc}, // document to insert when nothing was found
{ upsert: true, new: true, runValidators: true }
)
请注意,您还应该为 filter
中包含的字段创建唯一索引,然后处理重复错误的可能性。请参阅