> For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

# $setIntersection  (expression operator)

## Definition

Takes two or more arrays and returns an array that contains the elements that appear in every input array.

[`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) has the following syntax:

```javascript
{ $setIntersection: [ <expression1>, <expression2>, ... ] }
```

The arguments can be any valid [expression](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions) if they each resolve to an array. For more information on expressions, see [Expressions.](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions)

## Behavior

[`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) performs set operation on arrays, treating arrays as sets. If an array contains duplicate entries, [`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) ignores the duplicate entries. [`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) ignores the order of the elements.

[`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) filters out duplicates in its result to output an array that contains only unique entries. The order of the elements in the output array is unspecified.

If no intersections are found (i.e. the input arrays contain no common elements), [`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) returns an empty array.

If a set contains a nested array element, [`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) does *not* descend into the nested array but evaluates the array at top-level.

| Example | Result | Notes |
| --- | --- | --- |
| `{ $setIntersection: [
  [ "a", "c" ],
  [ "a", "b" ]
] }` | `[ "a" ]` | The only common element between the two arrays is `"a"`. |
| `{ $setIntersection: [
  [ "a", "c" ],
  [ "a", "b", "c" ]
] }` | `[ "a", "c" ]` | `"a"` and `"c"` are common elements between the two arrays. |
| `{ $setIntersection: [
  [ "a", "b", "a" ],
  [ "b", "a" ]
] }` | `[ "b", "a" ]` | `"b"` and `"a"` are common elements between the two arrays. |
| `{ $setIntersection: [
  [ "a", "b" ],
  [ [ "a", "b" ] ]
] }` | `[ ]` | There are no common elements between the two arrays. The string elements `"a"` and `"b"` are not equal to the array `[ "a", "b" ]`. |
| `{ $setIntersection: [
  [ ],
  [ "a", "b" ]
] }` | `[ ]` | There are no common elements between the two arrays because the first array is empty. |
| `{ $setIntersection: [
  [ "a", "a" ],
  [ "a", "b" ]
] }` | `[ "a" ]` | The only common element is `"a"` and it appears once in the result because only unique elements are considered. |

## Examples

This section contains examples that show the use of `$setIntersection` with collections.

### Elements Array Example

Consider an `flowers` collection with the following documents:

```javascript
db.flowers.insertMany( [
   { "_id" : 1, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid" ] },
   { "_id" : 2, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "orchid", "rose", "orchid" ] },
   { "_id" : 3, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid", "jasmine" ] },
   { "_id" : 4, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "jasmine", "rose" ] },
   { "_id" : 5, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ ] },
   { "_id" : 6, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose" ], [ "orchid" ] ] },
   { "_id" : 7, "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose", "orchid" ] ] },
   { "_id" : 8, "flowerFieldA" : [ ], "flowerFieldB" : [ ] },
   { "_id" : 9, "flowerFieldA" : [ ], "flowerFieldB" : [ "rose" ] }
] )
```

The following operation uses the [`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) operator to return an array of elements common to both the `flowerFieldA` array and the `flowerFieldB` array:

```javascript
db.flowers.aggregate(
   [
     { $project: { flowerFieldA: 1, flowerFieldB: 1, commonToBoth: { $setIntersection: [ "$flowerFieldA", "$flowerFieldB" ] }, _id: 0 } }
   ]
)
```

The operation returns the following results:

```javascript
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid" ], "commonToBoth" : [ "orchid", "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "orchid", "rose", "orchid" ], "commonToBoth" : [ "orchid", "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "rose", "orchid", "jasmine" ], "commonToBoth" : [ "orchid", "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ "jasmine", "rose" ], "commonToBoth" : [ "rose" ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose" ], [ "orchid" ] ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ "rose", "orchid" ], "flowerFieldB" : [ [ "rose", "orchid" ] ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ ], "flowerFieldB" : [ ], "commonToBoth" : [ ] }
{ "flowerFieldA" : [ ], "flowerFieldB" : [ "rose" ], "commonToBoth" : [ ] }
```

### Retrieve Documents for Roles Granted to the Current User

Starting in MongoDB 7.0, you can use the new [`USER_ROLES`](https://www.mongodb.com/docs/manual/reference/aggregation-variables.md#mongodb-variable-variable.USER_ROLES) system variable to return user [roles.](https://www.mongodb.com/docs/manual/core/authorization.md#std-label-roles)

The scenario in this section shows users with various roles who have limited access to documents in a collection containing budget information.

The scenario shows one possible use of `USER_ROLES`. The `budget` collection contains documents with a field named `allowedRoles`. As you'll see in the following scenario, you can write queries that compare the user roles found in the `allowedRoles` field with the roles returned by the `USER_ROLES` system variable.

**Note:**

For another `USER_ROLES` example scenario, see [Retrieve Medical Information for Roles Granted to the Current User](https://www.mongodb.com/docs/manual/core/views/create-view.md#std-label-create-view-user-roles-system-variable-medical-example). That example doesn't store the user roles in the document fields, as is done in the following example.

For the budget scenario in this section, perform the following steps to create the roles, users, and `budget` collection:

1. Create the roles

   Run:

   ```javascript
   db.createRole( { role: "Marketing", roles: [], privileges: [] } )
   db.createRole( { role: "Sales", roles: [], privileges: [] } )
   db.createRole( { role: "Development", roles: [], privileges: [] } )
   db.createRole( { role: "Operations", roles: [], privileges: [] } )
   ```

2. Create the users

   Create users named `John` and `Jane` with the required roles. Replace the `test` database with your database name.

   ```javascript
   db.createUser( {
      user: "John",
      pwd: "jn008",
      roles: [
         { role: "Marketing", db: "test" },
         { role: "Development", db: "test" },
         { role: "Operations", db: "test" },
         { role: "read", db: "test" }
      ]
   } )

   db.createUser( {
      user: "Jane",
      pwd: "je009",
      roles: [
         { role: "Sales", db: "test" },
         { role: "Operations", db: "test" },
         { role: "read", db: "test" }
      ]
   } )
   ```

3. Create the collection

   Run:

   ```javascript
   db.budget.insertMany( [
      {
         _id: 0,
         allowedRoles: [ "Marketing" ],
         comment: "For marketing team",
         yearlyBudget: 15000
      },
      {
         _id: 1,
         allowedRoles: [ "Sales" ],
         comment: "For sales team",
         yearlyBudget: 17000,
         salesEventsBudget: 1000
      },
      {
         _id: 2,
         allowedRoles: [ "Operations" ],
         comment: "For operations team",
         yearlyBudget: 19000,
         cloudBudget: 12000
      },
      {
         _id: 3,
         allowedRoles: [ "Development" ],
         comment: "For development team",
         yearlyBudget: 27000
      }
   ] )
   ```

Perform the following steps to retrieve the documents accessible to `John`:

1. Log in as John

   Run:

   ```javascript
   db.auth( "John", "jn008" )
   ```

2. Retrieve the documents

   To use a system variable, add `$$` to the start of the variable name. Specify the `USER_ROLES` system variable as `$$USER_ROLES`.

   Run:

   ```javascript
   db.budget.aggregate( [ {
      $match: {
         $expr: {
            $not: {
               $eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
            }
         }
      }
   } ] )
   ```

   The previous example returns the documents from the `budget` collection that match at least one of the roles that the user who runs the example has. To do that, the example uses [`$setIntersection`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setintersection.md#mongodb-expression-exp.-setIntersection) to return documents where the intersection between the `budget` document `allowedRoles` field and the set of user roles from `$$USER_ROLES` is not empty.

3. Examine the documents

   `John` has the `Marketing`, `Operations`, and `Development` roles, and sees these documents:

   ```javascript
   [
      {
         _id: 0,
         allowedRoles: [ 'Marketing' ],
         comment: 'For marketing team',
         yearlyBudget: 15000
      },
      {
         _id: 2,
         allowedRoles: [ 'Operations' ],
         comment: 'For operations team',
         yearlyBudget: 19000,
         cloudBudget: 12000
      },
      {
         _id: 3,
         allowedRoles: [ 'Development' ],
         comment: 'For development team',
         yearlyBudget: 27000
      }
   ]
   ```

Perform the following steps to retrieve the documents accessible to `Jane`:

1. Log in as Jane

   Run:

   ```javascript
   db.auth( "Jane", "je009" )
   ```

2. Retrieve the documents

   To use a system variable, add `$$` to the start of the variable name. Specify the `USER_ROLES` system variable as `$$USER_ROLES`.

   Run:

   ```javascript
   db.budget.aggregate( [ {
      $match: {
         $expr: {
            $not: {
               $eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
            }
         }
      }
   } ] )
   ```

3. Examine the documents

   `Jane` has the `Sales` and `Operations` roles, and sees these documents:

   ```javascript
   [
      {
         _id: 1,
         allowedRoles: [ 'Sales' ],
         comment: 'For sales team',
         yearlyBudget: 17000,
         salesEventsBudget: 1000
      },
      {
         _id: 2,
         allowedRoles: [ 'Operations' ],
         comment: 'For operations team',
         yearlyBudget: 19000,
         cloudBudget: 12000
      }
   ]
   ```

   **Note:**

   On a sharded cluster, a query can be run on a shard by another server node on behalf of the user. In those queries, `USER_ROLES` is still populated with the roles for the user.
