How to do a full match search with two parameters?

113 views Asked by At

I have database model

Schema({
  members: [
    {
      type: String,
      required: true,
      ref: "User"
    }
  ],
  createdAt: {
    type: Date,
    default: Date.now(),
    required: true
  },
  lastMessage: {
    message: {
      type: String,
      required: true
    },
    from: {
      type: String,
      required: true
    },
    createdAt: {
      type: Date,
      required: true
    }
  },
  messages: [
    {
      createdAt: {
        type: Date,
        required: true
      },
      message: {
        type: String,
        required: true
      },
      from: {
        type: String,
        ref: "User",
        required: true
      }
    }
  ]
});

That code I use to find some documents

Chats.countDocuments(
      {
        members: {
          $in: ["userIdOne", "userIdTwo"]
        }
      },
      cb
    )

I use $in to find data what I need, but $in find all documents which contains one of this userId.... Me need to find only one document which contains that user's ids.

How can i do this?

2

There are 2 answers

3
Valijon On BEST ANSWER

Use $all instead

Chats.countDocuments(
  {
    members: {
      $all: ["userIdOne", "userIdTwo"]
    }
  },
  cb
)
2
SuleymanSah On

If you need exact match, you can use $setEquals aggregation operator.

db.collection.aggregate([
  {
    $match: {
      $expr: {
        $eq: [
          {
            $setEquals: [
              "$members",
              [
                "userIdOne",
                "userIdTwo"
              ]
            ]
          },
          true
        ]
      }
    }
  },
  {
    $count: "count"
  }
])

Input:

[
  {
    "members": [
      "userIdOne"
    ]
  },
  {
    "members": [
      "userIdTwo"
    ]
  },
  {
    "members": [
      "userIdOne",
      "userIdTwo"
    ]
  },
  {
    "members": [
      "userIdOne",
      "userIdTwo",
      "userIdThere"
    ]
  }
]

Output:

[
  {
    "count": 1
  }
]

Playground

You can integrate this to mongoose like this:

  const result = await Chats.aggregate([
    {
      $match: {
        $expr: {
          $eq: [
            {
              $setEquals: ["$members", ["userIdOne", "userIdTwo"]]
            },
            true
          ]
        }
      }
    },
    {
      $count: "count"
    }
  ]);

  const count = result[0].count;