我的架构如下:
{
_id: mongoose.Schema.Types.ObjectId,
timestamp: { type: Date, default: Date.now },
uid: { type: String, required: false, immutable: true },
gid: [
{
type: String
}
],
status: { type: String, required: false }
}
我希望每次uid
是新对象时都可以保存一个新对象,并在已有对象时对其进行更新。因此,基本上保存此对象:
{
uid: "xyz",
gid: "123"
}
应该产生
{
_id: ObjectId("123"),
uid: "xyz",
gid: ["123"]
// note that if status is not provided it shouldn't appear here as `null`
}
然后再次保存该对象:
{
uid: "xyz",
gid: "345",
status: "new"
}
它应该产生:
{
_id: ObjectId("123"),
uid: "xyz",
gid: ["123","345"]
status: "new"
}
最后是这个对象:
{
uid: "xyz",
gid: "345",
status: "old"
}
预期结果将是
{
_id: ObjectId("123"),
uid: "xyz",
gid: ["123","345"]
status: "old"
}
这可以在单个查询中实现吗?抱歉,如果我的求职过程很复杂,我不知道该怎么办。
答案 0 :(得分:0)
案例1:仅状态更改和数组存在,下面的代码将不会添加新元素
> //actual code output from Mongo shell 4.2 on windows10 OS
> //use add to set and set update to acheive your update goals(array vs addition
> //of fields in two updates
> //add to set checks for an array element is present in array, if it is present it does nothing
> //else it will add the element in the array
> //pre-update document check
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200"
],
"status" : "old"
}
> var v_status = "new";
> db.ugs.aggregate([
... {$match:{uid: "xyz"}}
... ]).forEach(function(doc){
... print("uid: ", doc.uid);
... print("gid: ",doc.gid);
... print("pre-status: ", doc.status);
... db.ugs.update(
... {"_id":doc._id},
... {$addToSet:{gid:"200"}
... });
... db.ugs.update(
... {"_id":doc._id},
... {$set:{status:v_status}}
... );
... print("post-status: ", v_status);
... });
uid: xyz
gid: 345,123,100,200
pre-status: old
post-status: new
> //post update document check
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200"
],
"status" : "new"
}
>
情况2:如果数组中不存在元素,请更改状态并添加元素
> //pre-update document check
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200"
],
"status" : "new"
}
> var v_status = "old";
> db.ugs.aggregate([
... {$match:{uid: "xyz"}}
... ]).forEach(function(doc){
... print("uid: ", doc.uid);
... print("gid: ",doc.gid);
... print("pre-status: ", doc.status);
... db.ugs.update(
... {"_id":doc._id},
... {$addToSet:{gid:"444"}
... });
... db.ugs.update(
... {"_id":doc._id},
... {$set:{status:v_status}}
... );
... print("post-status: ", v_status);
... });
uid: xyz
gid: 345,123,100,200
pre-status: new
post-status: old
> //post update document check
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200",
"444"
],
"status" : "old"
}
>
情况3:根据需要设置和取消设置状态字段的值。
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200",
"444"
],
"status" : ""
}
> var v_status = "";
> db.ugs.aggregate([
... {$match:{uid: "xyz"}}
... ]).forEach(function(doc){
... print("uid: ", doc.uid);
... print("gid: ",doc.gid);
... print("pre-status: ", doc.status);
... db.ugs.update(
... {"_id":doc._id},
... {$addToSet:{gid:"444"}
... });
... db.ugs.update(
... {"_id":doc._id,status:{$exists:true}},
... {$set:{status:v_status}}
... );
... print("post-status: ", v_status);
... });
uid: xyz
gid: 345,123,100,200,444
pre-status:
post-status:
> //post update document check
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200",
"444"
],
"status" : ""
}
//unset the field if not required, it will not show in the document
> var v_status = "";
> db.ugs.aggregate([
... {$match:{uid: "xyz"}}
... ]).forEach(function(doc){
... print("uid: ", doc.uid);
... print("gid: ",doc.gid);
... print("pre-status: ", doc.status);
... db.ugs.update(
... {"_id":doc._id},
... {$addToSet:{gid:"444"}
... });
... db.ugs.update(
... {"_id":doc._id,status:{$exists:true}},
... {$unset:{status:v_status}}
... );
... print("post-status: ", v_status);
... });
uid: xyz
gid: 345,123,100,200,444
pre-status: [unknown type]
post-status:
> //post update document check
> db.ugs.find().pretty();
{
"_id" : ObjectId("5f625d864651219e25c775c1"),
"uid" : "xyz",
"gid" : [
"345",
"123",
"100",
"200",
"444"
]
}
>
答案 1 :(得分:0)
您正在寻找upsert
选项来添加新文档(如果尚不存在)。与addToSet
原子运算符结合使用,创建了一个gid数组。
您必须将其余部分分解为$ set和$ addToSet更新程序。
let saveObj = {
uid: "xyz",
gid: "123"
};
let {gid, ...setFields} = saveObj;
YourModel.updateOne(
{uid: setFields.uid},
{$set: setFields, $addToSet: {gid}},
{upsert: true}
).then(...);