1

Here's my data structure:

db.getCollection('competitionmatches').find()
{
    "_id" : ObjectId("5d2d9eed5972a9367cd5010a"),
    "matches" : [ 
        {
            "id" : 200000,
            "utcDate" : "",
            "minute" : null,
            "homeTeam" : {
                "id" : 808,
                "coach" : {},
            },
            "goals" : [{},{}}],
        },
        {...},
        {...},
    ],
    "otherField": []
},
{...},
{...},

What i'm trying to remove are those fields: minute, coach and goals in all matches of all entries in competitionmatches.

I've tried the following in Robo 3T with success:

db.getCollection('competitionmatches').update({}, {$unset: {"otherField":""}})

This removes well the whole array otherField in each element of matches if i pass multi:true (removed here for the sake of readability).

But when i try:

db.getCollection('competitionmatches').update({}, {$unset: {"matches.$[].goals":""}})

or

db.getCollection('competitionmatches').update({}, {$unset: {"matches.$[].minute":""}})

i get a success message Updated 1 existing record(s) in 3ms but the record stay the same, minute or goals do not get removed.

I got this answer from Remove a field from all elements in array in mongodb and updated my mongo version from 3.4 to 3.6 because the $[] was introduced in 3.6 as said by svr and shown in the docs.

Unset works but the path seems to be the wrong part of my update.

"matches.$.goals" returns an error and matches.[].goals does not have any impact as well. I was even wondering if there could be some cache but that does not make much sense since the unset on otherField gets executed well.

I was also in doubt if the update went well but the app using the database works fine as far as i can see.

turivishal
  • 34,368
  • 7
  • 36
  • 59
kevin
  • 618
  • 8
  • 24

1 Answers1

2

The update can't access direct array field using $ or $[], we need to provide query to match in array,

db.getCollection('competitionmatches').update(
  // it requires to specify any one field match condition in query part
  { "matches.goals": { $exists: true } }, 
  { 
    $unset: { 
      "matches.$[].minute": true // pass true
      "matches.$[].homeTeam.coach": true // pass true
      "matches.$[].goals": true // pass true
    } 
  } 
);

Mongo shell

> db.upd22.find()
[
  {
    _id: ObjectId("5d2d9eed5972a9367cd5010a"),
    matches: [
      {
        id: 200000,
        utcDate: '',
        minute: null,
        homeTeam: { id: 808, coach: {} },
        goals: [ {}, {} ]
      },
      {
        id: 300000,
        utcDate: '',
        minute: null,
        homeTeam: { id: 808, coach: {} },
        goals: [ {}, {} ]
      }
    ]
  },
  {
    _id: ObjectId("5d2d9eed5972a9367cd5010b"),
    matches: [
      {
        id: 400000,
        utcDate: '',
        minute: null,
        homeTeam: { id: 808, coach: {} },
        goals: [ {}, {} ]
      },
      {
        id: 500000,
        utcDate: '',
>                                                                                                                                          homeTeam: { id: 808, coach: {} },
        goals: [ {}, {} ]
      }
    ]
  }
]
> db.getCollection('upd22').update(
...     { "matches.goals": { $exists: true } },
...     {
.....         $unset: {
.......             "matches.$[].minute": true,
.......             "matches.$[].goals": true
.......         }
.....     },
...     { multi: false }
... )
{
  acknowledged: 1,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
> db.upd22.find()
[
  {
    _id: ObjectId("5d2d9eed5972a9367cd5010a"),
    matches: [
      { id: 200000, utcDate: '', homeTeam: { id: 808, coach: {} } },
      { id: 300000, utcDate: '', homeTeam: { id: 808, coach: {} } }
    ]
  },
  {
    _id: ObjectId("5d2d9eed5972a9367cd5010b"),
    matches: [
      {
        id: 400000,
        utcDate: '',
        minute: null,
        homeTeam: { id: 808, coach: {} },
        goals: [ {}, {} ]
      },
      {
        id: 500000,
        utcDate: '',
        minute: null,
        homeTeam: { id: 808, coach: {} },
        goals: [ {}, {} ]
      }
    ]
  }
]
>
turivishal
  • 34,368
  • 7
  • 36
  • 59
  • Just tried but no luck. I used the following:`db.getCollection('competitionmatches').update({ "matches.goals": { $exists: true } }, { $unset: { "matches.$[].minute": true, "matches.$[].goals": true}} , { multi:false })` Note, `coach` is within the `homeTeam` object. – kevin Sep 02 '20 at 00:00
  • its removing both fields from first document, that is not working your side? – turivishal Sep 02 '20 at 03:57
  • i get an "Updated 1 existing record(s)" as the result but when refreshing the data with a new `find()` i can still see bopth fields in at least the first two entries of the array `matches`. – kevin Sep 02 '20 at 10:03
  • I've narrowed the query to a specific `competitionMatches` by id with `db.getCollection('competitionmatches').update({ "_id": ObjectId("5d2d9eed5972a9367cd5010a"), "matches.goals": { $exists: true } }, { $unset: { "matches.$[].minute": true, "matches.$[].goals": true}} , { multi:false })` – kevin Sep 02 '20 at 10:04
  • Just did a quick test by adding at the root of the `competitionMatches` with the id above a field `temporary` and removing it with `db.getCollection('competitionmatches').update({ "_id": ObjectId("5d2d9eed5972a9367cd5010a"), "matches.goals": { $exists: true } }, { $unset: { "tempo":true, "matches.$[].minute": true, "matches.$[].goals": true}} , { multi:false })` and it worked. So i guess the problem os really entering the array and finding the desired fields. – kevin Sep 02 '20 at 10:07
  • not sure why its not working in your machine, might be some versioning issues. – turivishal Sep 02 '20 at 10:14