我有一份如下文件:
{
_id: "00112233",
array: [
{
_id: "potatoes",
amount: 5
},
{
_id: "carrots",
amount: 6
}
]
}
我需要更新或推送文档,这样如果数组中有一个文档,则会被替换,如果没有,则会被推送。
如果我尝试进行这样的更新:
db.collection.update(
{ _id: "00112233" },
{
"$push": { "array": { "$each": [
{
_id: "potatoes",
amount: 6
},
{
_id: "apples",
amount: 2
}
]}}
}
)
在数据库中,我会找到两个“土豆”字段。但如果我尝试用“addToSet”替换“推”,我将不会更新“土豆”字段。
有什么方法可以只在一个查询中执行此操作吗?
答案 0 :(得分:2)
不幸的是,您无法达到单个更新操作所期望的结果。
addToSet
不适用于此方案,因为该阵列具有嵌入的文档。 addToSet
检查属性名称和值是否匹配。如果找到匹配,则不执行任何操作。如果未找到匹配项,则会将数据添加到数组属性中。
在上述“土豆”的情况下,土豆的数量值不匹配。所以它将一个新元素插入到数组中。所以结果有两个土豆有2个不同的值。
{
_id: "potatoes",
amount: 6
}
您可能需要执行两次更新操作。
1)使用$set
db.collection.update(
{ _id: "00112233", "array._id": "potatoes"},
{
"$set": { "array.$":
{
_id: "potatoes",
amount: 7
}
},
}
);
2)使用$addToSet
db.collection.update(
{ _id: "00112233"},
{
"$addToSet": { "array":
{
_id: "apples",
amount: 7
}
},
}
);
答案 1 :(得分:0)
您需要使用$set
代替$push/$addToSet
。
https://docs.mongodb.com/manual/reference/operator/update/set/
答案 2 :(得分:0)
遇到类似的问题并尝试了概念探索的方法,它确实起作用了。我的模式如下
neighbors=[]
我想更新以下matchInstances子文档,如果存在匹配项,其伪关键字与顶级(父文档)伪关键字相同,而没有 复制值,如果不存在则在matchInstances子文档中创建一个新条目。
const MatchInstanceSchema = new Schema({
_id: false,
pseudoKey: { type: String, required: true, unique: true },
service: { type: String, required: true },
region: { type: String, required: true },
team1: {
name: { type: String, required: true },
price: { type: String, required: true }
},
team2: {
name: { type: String, required: true },
price: { type: String, required: true }
},
drawPrice: { type: String, required: true },
url: { type: String, required: true }
})
const MatchSchema = new Schema({
pseudoKey: { type: String, required: true, unique: true },
sport: { type: String, required: true },
league: { type: String, required: true },
date: { type: Date, required: true },
team1: { type: String, required: true },
team2: { type: String, required: true },
matchInstances: [MatchInstanceSchema]
})
这是我的解决方法
{
"_id" : ObjectId("5b47d47e7fd01d29178aa3a5"),
"pseudoKey" : "newcastle-tottenham",
"sport" : "Soccer",
"league" : "Premier League",
"date" : ISODate("2018-08-11T11:30:00.000Z"),
"team1" : "Newcastle",
"team2" : "Tottenham",
"matchInstances" : [
{
"team1" : {
"name" : "Newcastle",
"price" : "74.6"
},
"team2" : {
"name" : "Tottenham",
"price" : "2.06"
},
"pseudoKey" : "newcastle-tottenham",
"service" : "Betin",
"region" : "Kenya",
"drawPrice" : "3.45",
"url" : "https://web.betin.co.ke/Sport/SubEventOdds.aspx?SubEventID=16701401"
}
]