Hello, i have a question about the following, in my database i have save a user with his login infos as a document into the “users” collection. I want to add into this user a couple of “user questions”, the questions i want to write as a object which contains all questions. I see now during testing that my querys does update all user questions, what i want to have is that a user question gets only updated if already exist or it should be add if not exist. What i understand currently is that the databse does see my query for insert and update like a query which should update the complete questions object, but i want the query to only update the questions which already exist or that it adds the questions as a new object entry if the questions does not already exist and every questions also have one number, so maybe it could be possible to archive this, but i dont know how to write the query correctly, please take a look at my current database entry and my query:
If ai understand correctly you are looking for an upsert whithin an array , I think there are 2 ways :
- Use array filters with upsert: true
- Use aggregation pipeline update with $zip on the array.
I will try to write an example for you.
Thanks
Pavel
So I noticed that you are using questions as an object and not array of objects. So my previous comment is irrelevant.
In that case a simple update will update or insert new fields:
db.users2.updateOne({"name" : "phil"},{$set : {"questions.nr1" : 1, "questions.question1" : "how am i?", "questions.answer1" : "bad"}})
{ acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0 }
{ _id: ObjectId("606d6cf0d81fef690531cedf"),
name: 'phil',
email: 'phil@example.com',
questions:
{ nr1: 1,
question1: 'how am i?',
answer1: 'bad',
nr2: 2,
question2: 'how are you?',
answer2: 'good' } }
db.users2.updateOne({"name" : "phil"},{$set : {"questions.nr3" : 3, "questions.question3" : "how am i?", "questions.answer3" : "good"}})
{ acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0 }
db.users2.findOne()
{ _id: ObjectId("606d6cf0d81fef690531cedf"),
name: 'phil',
email: 'phil@example.com',
questions:
{ nr1: 1,
question1: 'how am i?',
answer1: 'bad',
nr2: 2,
question2: 'how are you?',
answer2: 'good',
answer3: 'good',
nr3: 3,
question3: 'how am i?' } }
Thanks,
Pavel
thank you i will check your example soon, currently i have create somethink with 2 querys where the first query try a $set and if the matchedcount from the query results is 0 then i have code to make a $addtoset query to add then new questions, but i think your example if it does the same work with only one query will be better, or?
addToSet is only if questions is an array , but its not…
I have build afterward a new construct where i use a array of objects, in my current codeing its works with AddtoSet and 2 database querys but i want to try also your solution, because i will find it better if i can do both taks with only one query.
Using an array and not naming convention of a nested object makes more sense here. If fields are named the same its eaiser to index them and operate objects.
So I will suggest you try to use a 2 command approach rather than having a bad structure.
Best regards,
Pavel