# $scoreFusion (aggregation)

The `$rankFusion` and `$scoreFusion` stages are available as Preview features. To learn more, see [Preview Features](https://www.mongodb.com/docs/preview-features/).`$scoreFusion` is only available for deployments that use MongoDB 8.2+.

## Definition

`$scoreFusion`
`$scoreFusion` first executes all input pipelines independently and then de-duplicates and combines the input pipeline results into a final scored results set.

`$scoreFusion` outputs a ranked set of documents based on the scores of the documents and weights from their input pipelines. You can specify an arithmetic expression to compute the score based on the input scores from the pipeline stage. By default, it uses the average of the scores for the documents from the different input pipeline stages.

Use `$scoreFusion` to search for documents in a single collection based on multiple criteria and retrieve a final scored result set that factors in all specified criteria.

## Syntax

The stage has the following syntax:

```javascript
{ $scoreFusion: {
    input: {
      pipelines: {
            <input-pipeline-name>: <expression>,
            <input-pipeline-name>: <expression>,
            ...
      },
      normalization: "none|sigmoid|minMaxScaler"
    },
    combination: {
      weights: {
            <input-pipeline-name>: <numeric expression>,
            <input-pipeline-name>: <numeric expression>,
            ...
      },
      method: "avg|expression",
      expression: <expression>
    }
} }
```

### Fields

`$scoreFusion` takes the following fields:

<table>
<tr>
<th id="Field">
Field

</th>
<th id="Type">
Type

</th>
<th id="Description">
Description

</th>
</tr>
<tr>
<td headers="Field">
`input`

</td>
<td headers="Type">
Object

</td>
<td headers="Description">
Defines the input that `$scoreFusion` combines.

</td>
</tr>
<tr>
<td headers="Field">
`input.``pipelines`

</td>
<td headers="Type">
Object

</td>
<td headers="Description">
Contains a map of pipeline names to the aggregation stages that define that pipeline. `input.pipelines` must contain at least one pipeline. You must specify [`$score`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/score/#mongodb-pipeline-pipe.-score) to the input pipeline if the input pipeline doesn't return a score. All pipelines must operate on the same collection and must have a unique name.

For more information on input pipeline restrictions, see [Input Pipelines](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/scoreFusion/#std-label-scoreFusion-input-pipelines) and [Input Pipeline Names](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/scoreFusion/#std-label-scoreFusion-pipeline-names).

</td>
</tr>
<tr>
<td headers="Field">
`input.``normalization`

</td>
<td headers="Type">
String

</td>
<td headers="Description">
Normalizes the score to the range `0` to `1` before combining the results. Value can be:

- `none` - to not normalize.

- `sigmoid` - to apply [`$sigmoid`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/sigmoid/#mongodb-expression-exp.-sigmoid) expression.

- `minMaxScaler` - to apply the [`$minMaxScaler`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/minMaxScaler/#mongodb-group-grp.-minMaxScaler) window operator.

</td>
</tr>
<tr>
<td headers="Field">
`combination`

</td>
<td headers="Type">
Object

</td>
<td headers="Description">
Optional. Defines how to combine the `input` pipeline results.

</td>
</tr>
<tr>
<td headers="Field">
`combination.``weights`

</td>
<td headers="Type">
Object

</td>
<td headers="Description">
Optional. Weights to apply to the normalized input pipeline scores when combining the results. Corresponds to the input pipelines, one per pipeline. The default weight is `1` if any pipeline's weight is unspecified. Each weight value must be a non-negative number (whole or decimal). Weight can be `0`.

</td>
</tr>
<tr>
<td headers="Field">
`combination.``method`

</td>
<td headers="Type">
String

</td>
<td headers="Description">
Optional. Specifies method for combining scores. Value can be:

- `avg` - to calculate the average of the input scores.

- `expression` - to apply a custom aggregation expression that you specify in the `combination.expression` field.

If omitted, defaults to `avg`.

</td>
</tr>
<tr>
<td headers="Field">
`combination.``expression`

</td>
<td headers="Type">
Arithmetic Expression

</td>
<td headers="Description">
Optional. Specifies the logic for combining the input scores. This is the custom expression that is used when `combination.method` is set to `expression`. Within the expression, use the name of the input pipeline to represent the corresponding input score for a document.

Mutually exclusive with `combination.weights`.

</td>
</tr>
<tr>
<td headers="Field">
`scoreDetails`

</td>
<td headers="Type">
Boolean

</td>
<td headers="Description">
Optional. Specifies whether to include detailed scoring information from each input pipeline in the output document's metadata. If omitted, default to `false`.

</td>
</tr>
</table>

## Behavior

### Collections

You can only use `$scoreFusion` with a single collection. You cannot use this aggregation stage at a database scope.

### De-Duplication

`$scoreFusion` de-duplicates the results across multiple input pipelines in the final output. Each unique input document appears at most once in the `$scoreFusion` output, regardless of the number of times that the document appears in input pipeline outputs.

### Input Pipelines

Each `input` pipeline must be both a Selection Pipeline and a Scoring Pipeline.

#### Selection Pipeline

A Selection Pipeline retrieves a set of documents from a collection without performing any modifications after retrieval. `$scoreFusion` compares documents across different input pipelines which requires that all input pipelines output the same unmodified documents.

A selection pipeline must only contain the following stages:

<table>
<tr>
<th id="Type">
Type

</th>
<th id="Stages">
Stages

</th>
</tr>
<tr>
<td headers="Type">
Search Stages

</td>
<td headers="Stages">
- [`$match`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/match/#mongodb-pipeline-pipe.-match), including `$match` with [legacy text search](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/core/text-search/on-prem/#std-label-perform-text-search-onprem)
  [`$geoNear`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/geoNear/#mongodb-pipeline-pipe.-geoNear)

- [`$search`](https://www.mongodb.com/docs/atlas/atlas-search/aggregation-stages/search/#mongodb-pipeline-pipe.-search)

- [`$vectorSearch`](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/#mongodb-pipeline-pipe.-vectorSearch)

If you use `$geoNear` in a selection pipeline, you cannot specify `includeLogs` or `distanceField` because those fields modify documents.

</td>
</tr>
<tr>
<td headers="Type">
Ordering Stages

</td>
<td headers="Stages">
- [`$sort`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/sort/#mongodb-pipeline-pipe.-sort)

</td>
</tr>
<tr>
<td headers="Type">
Pagination Stages

</td>
<td headers="Stages">
- [`$skip`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/skip/#mongodb-pipeline-pipe.-skip)

- [`$limit`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/limit/#mongodb-pipeline-pipe.-limit)

</td>
</tr>
</table>

#### Scoring Pipeline

A scoring pipeline sorts or orders documents based on the score of the documents. `$scoreFusion` uses the order of scored pipeline results to influence the output scores. Scoring pipelines must meet one of the following criteria:

- Begin with one of the following ordered stages:

  - [`$search`](https://www.mongodb.com/docs/atlas/atlas-search/aggregation-stages/search/#mongodb-pipeline-pipe.-search)

  - [`$vectorSearch`](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/#mongodb-pipeline-pipe.-vectorSearch)

  - [`$match`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/match/#mongodb-pipeline-pipe.-match) with legacy text search

  - [`$geoNear`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/geoNear/#mongodb-pipeline-pipe.-geoNear)

- Contain an explicit [`$score`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/score/#mongodb-pipeline-pipe.-score) stage if the preceding pipeline doesn't inherently return a score.

### Input Pipeline Names

Pipeline names in `input` must meet the following restrictions:

- Must not be an empty string

- Must not start with a `$`

- Must not contain the ASCII null character delimiter `\0` anywhere in the string

- Must not contain a `.`

### scoreDetails

If you set `scoreDetails` to `true`, `$scoreFusion` creates a `scoreDetails` metadata field for each document. The `scoreDetails` field contains information about the final ranking.

When you set `scoreDetails` to `true`, `$scoreFusion` sets the `scoreDetails` metadata field for each document. By default, it doesn't automatically output the `scoreDetails` metafield.

To view the `scoreDetails` metadata field, you must explicitly set it through the [`$meta`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/meta/#mongodb-expression-exp.-meta) expression in a stage like [`$project`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/project/#mongodb-pipeline-pipe.-project), [`$addFields`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/addFields/#mongodb-pipeline-pipe.-addFields), or [`$set`](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/operator/aggregation/set/#mongodb-pipeline-pipe.-set).

The `scoreDetails` field contains the following subfields:

<table>
<tr>
<th id="Field">
Field

</th>
<th id="Description">
Description

</th>
</tr>
<tr>
<td headers="Field">
`value`

</td>
<td headers="Description">
The numerical value of the score for this document.

</td>
</tr>
<tr>
<td headers="Field">
`description`

</td>
<td headers="Description">
A description of how `$scoreFusion` computed the final score.

</td>
</tr>
<tr>
<td headers="Field">
`normalization`

</td>
<td headers="Description">
The normalization method used to normalize the score.

</td>
</tr>
<tr>
<td headers="Field">
`combination`

</td>
<td headers="Description">
The combination method and expression used to combine the pipeline results.

</td>
</tr>
<tr>
<td headers="Field">
`details`

</td>
<td headers="Description">
An array where each array entry contains information about the input pipelines that output this document.

</td>
</tr>
</table>Each array entry in the `details` field contains the following subfields:

<table>
<tr>
<th id="Field">
Field

</th>
<th id="Description">
Description

</th>
</tr>
<tr>
<td headers="Field">
`inputPipelineName`

</td>
<td headers="Description">
The name of the input pipeline that output this document.

</td>
</tr>
<tr>
<td headers="Field">
`inputPipelineRawScore`

</td>
<td headers="Description">
The score of the document from the pipeline before normalization.

</td>
</tr>
<tr>
<td headers="Field">
`weight`

</td>
<td headers="Description">
The weight of the input pipeline.

</td>
</tr>
<tr>
<td headers="Field">
`value`

</td>
<td headers="Description">
Optional. If the input pipeline outputs a `{ $meta: 'score' }` for this document, `value` contains `{ $meta: 'score' }`.

</td>
</tr>
<tr>
<td headers="Field">
`details`

</td>
<td headers="Description">
The `scoreDetails` field of the input pipeline. If the input pipeline does not output a `scoreDetails` field, this field is an empty array.

</td>
</tr>
</table>MongoDB does not guarantee any specific output format for `scoreDetails`.

The following code blocks show the `scoreDetails` field for a `$scoreFusion` operation with `$search`, `$vectorSearch`, and `$match` input pipelines:

```js
  :copyable: false
  scoreDetails: {
  value: 7.847857250621068,
  description: 'the value calculated by combining the scores (either normalized or raw) across input pipelines from which this document is output from:',
  normalization: 'sigmoid',
  combination: {
    method: 'custom expression',
    expression: "{ string: { $sum: [ { $multiply: [ '$$searchOne', 10 ] }, '$$searchTwo' ] } }"
  },
  details: [
    {
      inputPipelineName: 'searchOne',
      inputPipelineRawScore: 0.7987099885940552,
      weight: 1,
      value: 0.6896984675751023,
      details: []
    },
    {
      inputPipelineName: 'searchTwo',
      inputPipelineRawScore: 2.9629626274108887,
      weight: 1,
      value: 0.950872574870045,
      details: []
    }
  ]
}
```

### Explain Results

MongoDB converts `$scoreFusion` operations into a set of existing aggregation stages that, in combination, compute the output result prior to query execution. The [Explain Results](https://mongodbcom-cdn.staging.corp.mongodb.com/docs/reference/explain-results/#std-label-explain-results) for a `$scoreFusion` operation show the full execution of the underlying aggregation stages that `$scoreFusion` uses to compose the final result.

## Examples

This example uses a collection with embeddings and text fields. Create `search` and `vectorSearch` type indexes on the collection.

The following index definition automatically indexes all the dynamically indexable fields in the collection for running [`$search`](https://www.mongodb.com/docs/atlas/atlas-search/aggregation-stages/search/#mongodb-pipeline-pipe.-search) queries against the indexed fields.

```js
db.embedded_movies.createSearchIndex(
   "<INDEX_NAME>",
   {
      mappings: { dynamic: true }
   }
)
```

The following index definition indexes the field with the embeddings in the collection for running [`$vectorSearch`](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/#mongodb-pipeline-pipe.-vectorSearch) queries against that field.

```js
db.embedded_movies.createSearchIndex(
   "<INDEX_NAME>",
   "vectorSearch",
   {
      "fields": [
         {
            "type": "vector",
            "path": "<FIELD_NAME>",
            "numDimensions": <NUMBER_OF_DIMENSIONS>,
            "similarity": "dotProduct"
         }
      ]
   }
);
```

The following aggregation pipeline uses `$scoreFusion` with the following input pipelines:

<table>
<tr>
<th id="Pipeline">
Pipeline

</th>
<th id="Number%20of%20Documents%20Returned">
Number of Documents Returned

</th>
<th id="Description">
Description

</th>
</tr>
<tr>
<td headers="Pipeline">
`searchOne`

</td>
<td headers="Number%20of%20Documents%20Returned">
20

</td>
<td headers="Description">
Runs a vector search on the field indexed as `vector` type for the term specified as embeddings. The query considers up to 500 nearest neighbors, but limits the results to 20 documents.

</td>
</tr>
<tr>
<td headers="Pipeline">
`searchTwo`

</td>
<td headers="Number%20of%20Documents%20Returned">
20

</td>
<td headers="Description">
Runs a full-text search for the same term and limits the results to 20 documents.

</td>
</tr>
</table>```js
db.embedded_movies.aggregate( [
   {
      $scoreFusion: {
         input: {
            pipelines: {
               searchOne: [
                  {
                     "$vectorSearch": {
                        "index": "<INDEX_NAME>",
                        "path": "<FIELD_NAME>",
                        "queryVector": <QUERY_EMBEDDINGS>,
                        "numCandidates": <NUMBER_OF_NEAREST_NEIGHBORS_TO_CONSIDER>,
                        "limit": <NUBMER_OF_DOCUMENTS_TO_RETURN>
                     }
                  }
               ],
               searchTwo: [
                  {
                     "$search": {
                        "index": "<INDEX_NAME>",
                        "text": {
                           "query": "<QUERY_TERM>",
                           "path": "<FIELD_NAME>"
                        }
                     }
                  },
               ]
            },
            normalization: "sigmoid"
         },
         combination: {
            method: "expression",
            expression: {
               $sum: [
                 {$multiply: [ "$$searchOne", 10]}, "$$searchTwo"
               ]
            }
         },
         "scoreDetails": true
      }
   },
   {
      "$project": {
         _id: 1,
         title: 1,
         plot: 1,
         scoreDetails: {"$meta": "scoreDetails"}
      }
   },
   { $limit: 20 }
] )
```

This pipeline performs the following actions:

- Executes the `input` pipelines

- Combines the returned results

- Outputs the first 20 documents which are the top 20 ranked results of the `$scoreFusion` pipeline

