MongoDB updateOne($pull) 匹配一个文档,但没有从数组中删除它
Posted
技术标签:
【中文标题】MongoDB updateOne($pull) 匹配一个文档,但没有从数组中删除它【英文标题】:MongoDB updateOne($pull) is matching a document, but not removing it from an arrayMongoDB updateOne($pull) 匹配一个文档,但没有从数组中删除它 【发布时间】:2021-03-03 04:23:37 【问题描述】:我正在构建一个基于 Pokemon API MERN 的应用程序,用户可以在其中从搜索组件搜索 Pokemon 并将它们添加到他们的个人资料中。用户模式包含一个口袋妖怪数组,其中每个口袋妖怪都由一个包含 Pokedex 编号、口袋妖怪名称和精灵源链接数组的文档表示,以便每个口袋妖怪都可以映射到用户的配置文件。我正在使用 $push 运算符将搜索结果中的每个口袋妖怪从 put 请求中添加到用户的团队中,效果很好。就像在实际游戏中一样,每个用户一次只能在他们的团队中拥有 6 个口袋妖怪,但是一个用户的团队也可以包含相同口袋妖怪的副本,所以为了从用户的团队中删除口袋妖怪,我发送了一个 put请求当前登录用户的用户名以及要删除的口袋妖怪的_id。当我尝试这个请求时,它返回一个错误,说 n:1 已经匹配,但是文档不是从用户的口袋妖怪数组中提取的。
router.put("/del", auth, async (req, res) =>
// Find user
User.findOne( username: req.body.username ).then((user) =>
// Try updating Pokemon array
const offTeam = user
.updateOne( $pull: pokemon: _id: req.body.id , function(
err,
data
)
console.log("ERROR:", err, data, err.message);
)
.then((offTeam) =>
res.status(200).json(offTeam);
)
.catch((e) =>
return res.status(400).json( msg: e.message );
);
);
);
下面是返回的错误:
ERROR: null
n: 1,
nModified: 0,
opTime:
ts: Timestamp _bsontype: 'Timestamp', low_: 2, high_: 1605810353 ,
t: 4
,
electionId: 7fffffff0000000000000004,
ok: 1,
'$clusterTime':
clusterTime: Timestamp _bsontype: 'Timestamp', low_: 2, high_: 1605810353 ,
signature: hash: [Binary], keyId: [Long]
,
operationTime: Timestamp _bsontype: 'Timestamp', low_: 2, high_: 1605810353
编辑:链接到存储库,当前在删除分支中工作。 https://github.com/nrhill1/pokeMERN/tree/delete
编辑:这是我的个人资料示例。我正在尝试删除 Marill 和 Houndoom,但都不会删除。
_id
:5fb5ef14e664d5172ee5e1ed
username
:"nic"
email
:"nic@gmail.com"
password
:"$2a$10$kKfpdkmPMeWAS.22nulCSOkVeqKPGxiA5PL9D5WhPsU0pAznq/J2u"
pokemon
:
Array
0
:
Object
_id
:5fb5ef26e664d5172ee5e1ee
id
:229
name
:"houndoom"
sprites
:
Array
1
:
Object
_id
:5fb614318558521aac650a4c
id
:183
name
:"marill"
sprites
:
Array
0
:"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokem..."
1
:"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokem..."
reg_date
:2020-11-19T04:05:40.436+00:00
__v
:0
【问题讨论】:
您能发布一个文档示例和预期输出吗? @J.F.编辑了帖子并添加了我的用户资料 【参考方案1】:您可以使用$in
并将您想要拉入的 id 设置为这样的数组(如果您想添加更多元素,我认为这是未来最简单的方法):
db.collection.update(
"_id": "5fb5ef14e664d5172ee5e1ed",
,
"$pull":
"pokemon":
"id":
"$in": [
229,
183
]
,
"multi": true
)
查询首先匹配_id
(我猜是用户ID,但如果需要,您可以使用username
、email
或其他字段)然后拉出所有id
在数组内的口袋妖怪。在这种情况下,229
和 183
将被删除。
示例here
请注意,如果您使用方法updateMany()
,则不需要multi:true
。
使用猫鼬是相同的查询,但使用updateMany()
:
var idToUpdate = mongoose.Types.ObjectId(req.body.id)
var pokemonsToDelete = [229, 183]
var updated = await model.updateMany(
"_id": idToUpdate,
,
"$pull":
"pokemon":
"id":
"$in": pokemonsToDelete
)
【讨论】:
尝试将req.body.id
解析为ObjectId
。像这样的东西:mongoose.Types.ObjectId(req.body.id)
我已经测试过了,它对我有用。也许你错过了分享任何可能改变查询或任何缺失值的东西?
好的,所以我认为您误读了我原来的问题。我不能使用 pokedex 编号,因为这样它就不允许用户删除他们团队中重复的 pokemon 的副本。如果我想要一个由所有皮卡丘组成的团队,只要我只想删除一个皮卡丘,这个查询就会删除每个皮卡丘。
所以你想被pokemon _id
删除?然后用这个字段代替id
。
不费吹灰之力!非常感谢你的帮助。解决方法是将 _id 包装在 mongoose.Types.ObjectId(_id) 中。以上是关于MongoDB updateOne($pull) 匹配一个文档,但没有从数组中删除它的主要内容,如果未能解决你的问题,请参考以下文章
mongoose updateOne 功能:如果 $pull 不起作用则不更新
MongoDB中updateOne超过findOneAndUpdate的用例[重复]
在 MongoDB 中使用 updateOne 时如何访问 upsertedId