skip to Main Content

I have a collection:

[
  {
    users: [user2, user4]
  },
  {
    users: [user1, user2, user3]
  },
  {
    users: [user1, user3, user4]
  }
]

nested property "users" cannot contain the same user twice.

I find out that user2 is actually the same user as user1, so I update my documents.
My final result should look like this:

[
  {
    users: [user1, user4]
  },
  {
    users: [user1, user3]
  },
  {
    users: [user1, user3, user4]
  }
]

Document1 is updated: user2 becomes user1.
Document2 is updated: user2 is removed since user1 already exists.
Document3 is not updated.

The order of the users is not important.

How can I achieve this with updateMany?

2

Answers


  1. you can use the $addToSet operator to ensure unique values in the "users" array. Here’s an example using the MongoDB Node.js driver:

    const MongoClient = require('mongodb').MongoClient;
    
    async function updateDocuments() {
      const uri = 'mongodb://localhost:27017'; // Your database URI
      const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
    
      try {
        await client.connect();
    
        const database = client.db('your-database-name');
        const collection = database.collection('your-collection-name');
    
        // Update documents using updateMany
        await collection.updateMany(
          {},
          {
            $addToSet: {
              users: { $each: ['user1', 'user2'] } // Add all users to ensure uniqueness
            }
          }
        );
    
        // Remove user2 from all documents
        await collection.updateMany(
          { users: 'user2' },
          {
            $pull: {
              users: 'user2'
            }
          }
        );
    
        console.log('Documents updated successfully');
      } finally {
        await client.close();
      }
    }
    
    updateDocuments();
    
    Login or Signup to reply.
  2. Use $filter to get array without user2. $setUnion with an array [user1] to get the final users set

    db.collection.updateMany({
      users: "user2"
    },
    [
      {
        "$set": {
          "users": {
            "$setUnion": [
              {
                "$filter": {
                  "input": "$users",
                  "as": "u",
                  "cond": {
                    $ne: [
                      "$$u",
                      "user2"
                    ]
                  }
                }
              },
              [
                "user1"
              ]
            ]
          }
        }
      }
    ])
    

    Mongo Playground


    Playground does not allow usage of updateMany. You can ignore {multi: true} in the playground as it is simply a workaround/alternative to updateMany

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search