node.js - 使用 $push 对数组进行多次更新
问题描述
考虑以下文档框架
{
_id: "615749dce3438547adfff9bc",
items: [
{
type: "shirt",
color: "red",
sizes: [
{
label: "medium",
stock: 10,
price: 20,
},
{
label: "large",
stock: 30,
price: 40,
}
]
},
{
type: "shirt",
color: "green",
sizes: [
{
label: "small",
stock: 5,
price: 3,
},
{
label: "medium",
stock: 5,
price: 3,
},
]
}
]
}
当一个新项目进来时,我想插入一个新文档到items
,除非一个项目与新项目相同type
,color
在这种情况下,我只想合并sizes
到现有item
的sizes
.
sizes
不必是唯一的。
我尝试使用$push
withupsert: true
但arrayFilters
显然$push
忽略了arrayFilters
.
node
带mongodb
包。
解决方案
查询1
- 过滤以查看是否存在
- 如果存在要更新的地图,则在最后添加
*2 数组读取,但仍比 query2 快
db.collection.update({},
[
{
"$set": {
"newitem": {
"type": "shirt",
"color": "red",
"sizes": [
{
"label": "medium"
}
]
}
}
},
{
"$set": {
"found": {
"$ne": [
{
"$filter": {
"input": "$items",
"cond": {
"$and": [
{
"$eq": [
"$$this.type",
"$newitem.type"
]
},
{
"$eq": [
"$$this.color",
"$newitem.color"
]
}
]
}
}
},
[]
]
}
}
},
{
"$set": {
"items": {
"$cond": [
{
"$not": [
"$found"
]
},
{
"$concatArrays": [
"$items",
[
"$newitem"
]
]
},
{
"$map": {
"input": "$items",
"in": {
"$cond": [
{
"$and": [
{
"$eq": [
"$$this.type",
"$newitem.type"
]
},
{
"$eq": [
"$$this.color",
"$newitem.color"
]
}
]
},
{
"$mergeObjects": [
"$$this",
{
"sizes": {
"$concatArrays": [
"$$this.sizes",
"$newitem.sizes"
]
}
}
]
},
"$$this"
]
}
}
}
]
}
}
},
{
"$unset": [
"found",
"newitem"
]
}
])
Query2
(替代解决方案)
- 减少并进行更新
- 如果找到保持更新,否则在最后添加
*1 数组读取(但 concat 很慢,对于大数组,>500 个成员,如果您有大数组,请使用 query1)
*这是正常的方法,如果我们有一种快速的方法可以在数组末尾添加,但我们没有,所以 Query1 更快
db.collection.update({},
[
{
"$set": {
"newitem": {
"type": "shirt",
"color": "red",
"sizes": [
{
"label": "medium"
}
]
}
}
},
{
"$set": {
"items-found": {
"$reduce": {
"input": "$items",
"initialValue": {
"items": [],
"found": null
},
"in": {
"$cond": [
{
"$and": [
{
"$eq": [
"$$value.found",
null
]
},
{
"$eq": [
"$$this.type",
"$newitem.type"
]
},
{
"$eq": [
"$$this.color",
"$newitem.color"
]
}
]
},
{
"items": {
"$concatArrays": [
"$$value.items",
[
{
"$mergeObjects": [
"$$this",
{
"sizes": {
"$concatArrays": [
"$$this.sizes",
"$newitem.sizes"
]
}
}
]
}
]
]
},
"found": true
},
{
"items": {
"$concatArrays": [
"$$value.items",
[
"$$this"
]
]
},
"found": "$$value.found"
}
]
}
}
}
}
},
{
"$set": {
"items": {
"$cond": [
"$items-found.found",
"$items-found.items",
{
"$concatArrays": [
"$items-found.items",
[
"$newitem"
]
]
}
]
}
}
},
{
"$unset": [
"items-found",
"newitem"
]
}
])
推荐阅读
- r - R Shiny 数据表图像在浏览器中运行时未更新
- ios - 如何在 UITableView 中滚动到不完整的问题
- python-3.x - 使用 Python 从 url 下载 *.mp4 文件
- java - 使用 NamedNativeQuery 和 SqlResultSetMapping 映射任何集合
- reactjs - 部署到服务器的反应项目的“npm start”权限被拒绝
- javascript - 在捕获事件的同时禁用滚轮?
- node.js - 如何在具有嵌套依赖项的嵌套订阅中使用循环?
- sql - 访问查询/VBA 以从两个字段和连接值进行分组
- c# - VSTO 加载项 CustomTaskPane 在升级到 Word 2016/2019 后自行打开
- ios - 无法打开文件“AppName”,因为您无权查看它您没有权限。` 在 Xcode 10.1 中运行应用程序时