Awesome36
Awesome36

Reputation: 89

MongoDB: Automatically update documents that have been embedded in another document?

I'm fairly new to MongoDB so this approach might be bad in the first place. Currently I have two collections user and team. Collection team has the attribute owner and member which both are embedded user documents. The structure looks like this:

User:

{
    '_id': ObjectId('623dd71aeae1f01af1524d65'),
    'name': 'AwXYC',
    'verified': True
}

Team:

    '_id': ObjectId('623f0648145eadb2a47ff1fe'),
    'name': 'test',
    'owner': {'_id': ObjectId('623dd71aeae1f01af1524d65'), 'name': 'AwXYC', 'verified': True},
    'members': [
        {'_id': ObjectId('623dd71aeae1f01af1524d65'), 'name': 'AwXYC', 'verified': True},
        {'_id': ObjectId('623dd71aeae1f01af1524d65'), 'name': 'AwXYC', 'verified': True}
    ]
}

Now I perform an update that would change the name of the document in the user collection so it now looks like:

{
    '_id': ObjectId('623dd71aeae1f01af1524d65'),
    'name': 'AwNewName',
    'verified': True
}

My Goal is that a change in this collection would also change the values in the team document, but they currently are not affected at all and stay the same. Is there a way to automatically update the team collection? Is this data structure flawed or is there an alternative solution?

Upvotes: 0

Views: 186

Answers (1)

rickhg12hs
rickhg12hs

Reputation: 11932

I'm not sure how "fragile" this is (maybe try it on a test db?), but here's one way you might do it.

db.team.aggregate([
  {
    "$unwind": "$members"
  },
  {
    "$lookup": {
      "from": "user",
      "localField": "members._id",
      "foreignField": "_id",
      "pipeline": [
        {
          "$project": {
            "_id": 0,
            "name": 1
          }
        }
      ],
      "as": "newMemberName"
    }
  },
  {
    "$lookup": {
      "from": "user",
      "localField": "owner._id",
      "foreignField": "_id",
      "pipeline": [
        {
          "$project": {
            "_id": 0,
            "name": 1
          }
        }
      ],
      "as": "newOwnerName"
    }
  },
  {
    "$set": {
      "members.name": {
        "$ifNull": [
          {
            "$first": "$newMemberName.name"
          },
          "$members.name"
        ]
      },
      "owner.name": {
        "$ifNull": [
          {
            "$first": "$newOwnerName.name"
          },
          "$owner.name"
        ]
      }
    }
  },
  {
    "$group": {
      "_id": "$_id",
      "name": {
        "$first": "$name"
      },
      "members": {
        "$push": "$members"
      },
      "owner": {
        "$first": "$owner"
      }
    }
  }
])

Try it on mongoplayground.net.

Upvotes: 1

Related Questions