Update pipeline: conditioning $unset

Hi!

I am new to $cond and I just can’t get things to work or know if what I want to do is possible. I would like to do one of two things:

  1. Condition the $unset. Pseudo code:
{
    $cond: {
        if: { ‘notes.title’: { $exists: true } },
        then: {
            $unset: {
                ‘notes.highlights’: true,
            }
        },
        else: {
            $unset: {
                notes: true 
            }
        },
    }
}
  1. Condition the key of $unset. Pseudo code:
{
    $unset: {
        $cond: {
            if: { ‘notes.title’: { $exists: true } },
            then: { ‘notes.highlights’: true },
            else: { notes: true },
        }
    }
}

Thank you :slight_smile:

Hello @Scott_Wager, the $unset update pipeline stage is used to remove (or exclude) field(s) from the document in an update operation. I’d like some clarification about what you had posted.

Assuming the field notes is:

notes: {
  title: "some text",
  highlights: "some value"
}

The pseudo-code I am reading is:

if the field `notes.title` exists, 
then 'notes.highlights' = true // setting a boolean true (or is it remove this field)
else notes = true // setting a boolean true (or is it remove this field)

setting a boolean true (or is it remove this field) - what you are trying to say is not clear. Can you post a sample document with the two possible outcomes?

1 Like

Hi, thank you for the quick reply! I apologise for the confusion, I am removing fields.

This operation removes the ‘highlights’ key from the notes object

{
    $unset: { 'notes.highlights': true },
}

While this operation removes the ‘notes’ key from the document

{
    $unset: { 'notes': true },
}

If a ‘title’ key exists then I’d like the first operation to run, else, I’d like the second operation to run.

What I am trying to avoid: If ‘highlights’ is the only key in ‘notes’, when it is removed, an empty object is left behind.

@Scott_Wager, I have this solution (and it works fine). I suspect there might be “better” way of doing this. The syntax needs to be same for this to work.

Take these two sample documents:

{
        "_id" : 1,
        "fld" : 111,
        "notes" : {
                "title" : "some_title_1",
                "highlights" : "abc 123"
        }
}
{ "_id" : 2, "fld" : 222, "notes" : { "highlights" : "abc 999" } }

The update operation:

db.collection.updateMany(
  {},
  [
    { 
         $set: { 
             "notes.highlights": { $cond: { if: { $eq: [ { $type: "$notes.title" }, "string" ] },
                                            then: "$$REMOVE",
                                            else: "$notes.highlights"
              } }
         }
    },
    { 
         $set: { 
             notes: { $cond: { if: { $eq: [ { $type: "$notes.title" }, "string" ] },
                               then: "$notes",
                               else: "$$REMOVE"
             } } 
         }
     }
])

The result:

{ "_id" : 1, "fld" : 111, "notes" : { "title" : "some_title_1" } }
{ "_id" : 2, "fld" : 222 }
2 Likes

This worked perfectly, thank you so much!!

I also used ‘$not’ instead of ‘$eq’:
{ $not: ["$notes.highlights"] }

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.