hellcaster
hellcaster

Reputation: 79

How to get only unique values in Mongoose?

I need to take only unique values from collection. For example:

const userID = `user1`;
const users = await Chat
  .find({'$or': [{to: userID}, {from: userID}]})
  .select(`-_id to from`)
  .lean();

// users will be like:
[
 {from: `user1`, to: `user2`},
 {from: `user1`, to: `user2`},
 {from: `user1`, to: `user2`},
 {from: `user2`, to: `user1`},
 {from: `user3`, to: `user1`},
 // ... 10089 more items
];

// and I want this in result 
const result = [`user2`, `user3`]; // exclude current user too

I know that I can do this using JS. I can create an array from users and run new Set(), but it will be slow. Can Mongoose do this instead of me?

Upvotes: 4

Views: 661

Answers (1)

turivishal
turivishal

Reputation: 36144

You can try aggregation query,

  • $match your condition
  • $group by null and construct unique array of from user and to user
  • $setUnion to get unique users from from and to array
  • $filter to iterate loop of above union array and remove current user
const userID = mongoose.Types.ObjectId(`user1`);
const users = await Chat.aggregate([
  { $match: { $or: [{ to: userID }, { from: userID }] } },
  {
    $group: {
      _id: null,
      from: { $addToSet: "$from" },
      to: { $addToSet: "$to" }
    }
  },
  {
    $project: {
      _id: 0,
      users: {
        $filter: {
          input: { $setUnion: ["$from", "$to"] },
          cond: { $ne: ["$$this", userID] }
        }
      }
    }
  }
]).exec();

console.log(users[0].users);

Playground

Upvotes: 3

Related Questions