Insert or update into a object with one query

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:

Hi @Florian_Silbereisen,

If ai understand correctly you are looking for an upsert whithin an array , I think there are 2 ways :

  1. Use array filters with upsert: true
  2. Use aggregation pipeline update with $zip on the array.

I will try to write an example for you.

Thanks
Pavel

Hi @Florian_Silbereisen,

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?

@Florian_Silbereisen,

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.

Hi @Florian_Silbereisen,

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