Ikdemm
Ikdemm

Reputation: 2353

Conditional populate with mongoose

I'm facing a problem with Mongoose. I have multiple models:

I'm trying to fetch Transactions.

Each Transaction contains a senderWalletId and a receiverWalletId that have a reference to Wallet.

Wallets have a field called type that can be either Organization or User and a field called owner that contains a reference to either a User or an Organization. I achieved this through a ref path to the type property value of the same wallet, like this.

type: {
    type: String,
    enum: [
      'User',
      'Organization',
      'Moneypot',
    ],
  },
  owner: {
    type: Schema.Types.ObjectId,
    refPath: "type"
  }

Now, I want to populate the owner of receiverWalletId and senderWalletId. If the type is Organization, I want to retrieve the name, phoneNumber, and email. If the type is User, I want to retrieve firstName, lastNmae, email, and phoneNumber. I partially achieved this through this code:

.populate({
      path: 'senderWalletId',
      select: ['owner', 'type'],
      match: { type: { $eq: 'User' } },
      populate: {
        path: 'owner',
        select: ['firstName', 'lastName', 'phoneNumber', 'email']
      }
    })
    .populate({
      path: 'receiverWalletId',
      select: ['owner', 'type'],
      match: { type: { $eq: 'User' } },
      populate: {
        path: 'owner',
        select: ['firstName', 'lastName', 'phoneNumber', 'email']
      }
    })

Now the question is, how to make these populations retrieve name instead of firstName and lastName when the type equal to an organization

Upvotes: 0

Views: 556

Answers (1)

Ikdemm
Ikdemm

Reputation: 2353

I found a way around this by putting all the properties inside the select array, like this:

   .populate({
      path: 'senderWalletId',
      select: ['owner', 'type'],
      match: { type: { $eq: 'User' } },
      populate: {
        path: 'owner',
        select: ['name', 'firstName', 'lastName', 'phoneNumber', 'email']
      }
    })
    .populate({
      path: 'receiverWalletId',
      select: ['owner', 'type'],
      match: { type: { $eq: 'User' } },
      populate: {
        path: 'owner',
        select: ['name', 'firstName', 'lastName', 'phoneNumber', 'email']
      }
    })

The power of NoSQL comes to use now as the returned array contains firstName and lastName in case the wallet type is User, and it contains name for the case where it is an organization

Upvotes: 0

Related Questions