存在一个mongo文档,它链接了用户和汽车。它包含以下字段:
- 用户.userId
- 用户.汽车[]
- 用户已更新
- 用户创建
User.cars是嵌入文档的数组。如果不包含id为$carId的汽车,则需要编写一个查询,以便仅在此字段中插入一辆汽车
以下查询将每次为$userId和$carId创建一个新记录。它应该做的是要么不插入新记录,要么更新driven的值。
$qb
->findAndUpdate()
->upsert(true)
->field('userId')->equals($userId)
->field('cars.id')->notEqual($carId)
->field('cars')->addToSet([
'id' => $carId,
'driven' => new DateTime(),
])
->field('updated')->set(new DateTime())
->field('created')->setOnInsert(new DateTime())
->limit(1)
;
return $qb->getQuery()->execute();
从查询中删除notEqual($carId)将始终将记录插入User.cars,这也是不希望的。
最终的结果应该是User.cars只为每个carId包含一条记录。
如果以后不需要搜索cars
的数组,可以将其存储为对象,并使用$carId
作为关键字:
$qb
->findAndUpdate()
->upsert(true)
->field('userId')->equals($userId)
->field("cars.$carId")->set([
'id' => $carId,
'driven' => new DateTime(),
])
->field('updated')->set(new DateTime())
->field('created')->setOnInsert(new DateTime())
->limit(1)
;
return $qb->getQuery()->execute();
如果cars
在文档中映射为EmbedMany
,您可能需要将集合的策略更改为set
或atomicSet
(我建议后者),否则ODM将在每次保存数组时重新索引数组。
同样,此解决方案也有其缺点,根据您希望如何使用数据,这些缺点可能会被认为是严重的,但它解决了有问题的问题。
顺便说一下,->limit(1)
是多余的,因为->findAndUpdate()
正在使查询运行findAndModify
命令,该命令本质上对单个文档进行操作。