Availability: MongoDB replication pre-filtering is available for customers on our Team and Enterprise plans. Self-hosted deployments require the Enterprise Self-Hosted Edition.
config.source_table_options. The Service applies them during the initial snapshot and ongoing change-stream replication, before evaluating Sync Streams queries. A filter applies to the whole instance, independently of which client connects.
Prerequisites
- MongoDB 6.0 or later. Azure DocumentDB is not supported for pre-filtering.
- Post Images set to Auto-Configure (
post_images: auto_configure) or Read-only (post_images: read_only). Pre-filtering does not supportpost_images: off. - With Auto-Configure, grant the Service permission to enable
changeStreamPreAndPostImages. With Read-only, enable it yourself on every replicated collection. See MongoDB Permissions. - Source indexes that support your filters. Create them before deploying the Sync Config, because the initial snapshot starts after deployment.
Configure Pre-filtering
This example replicates only todos with an explicitarchived: false field. Each client receives only its own todos.
1
Create a Source Index
Run the following in The filtered field narrows the snapshot query. The final
mongosh against your source database:_id key lets MongoDB return each snapshot page in _id order without sorting all matching documents again. See Snapshot Indexes for filters on multiple fields.2
Add the Filter to Your Sync Config
$$doc refers to the source document. The pre-filter handles archived, so the SQL query does not need to repeat that condition. The owner_id condition still controls access for each client.This filter excludes documents where archived is missing. Set archived: false explicitly on every document you want to replicate.3
Deploy Your Sync Config
Deploy the Sync Config using your usual Cloud or self-hosted workflow. Deploy later filter changes as part of the Sync Config too.If validation reports an inefficient snapshot index, create the recommended index before deployment. Index warnings are advisory and do not block deployment.
Supported Expressions
Filters use a restricted subset of MongoDB aggregation expressions. The supported operators compare source fields against fixed values or combine other filters:
For
$eq and $in, put the source field first, using $$doc.<path>. Nested fields such as $$doc.customer.tier are supported. Numeric path segments, such as $$doc.items.0, are not supported. $in lists and $and or $or operands must be nonempty.
Constants can be strings, numbers, booleans, or BSON values expressed as Extended JSON (EJSON). For example, match an ObjectId with:
$oid, $date, $numberInt, $numberLong, $numberDouble, $numberDecimal, $timestamp, $binary, and $uuid. Plain integer constants must fit a signed 32-bit integer; use an explicit numeric wrapper for larger integers. For a literal string that starts with $, use $literal, such as { $literal: '$internal' }.
Filters do not support comparisons between fields, computed values, null, array constants, or embedded-document constants. Operators such as $ne, $not, $gt, and $lt are not supported. Use explicit values, such as archived: false, instead of conditions such as “not true” or “field is missing.”
Comparison Semantics
Pre-filters use MongoDB aggregation expressions. Their comparison behavior differs from the query predicates you might use infind().
Arrays and Nested Paths
$eq compares the field’s whole value against a constant. $in compares that whole value against each constant in the supplied list. Neither operator searches for matching elements inside an array-valued source field:
A native query such as
find({ store_id: 'store-a' }) can match the array in the last row. The pre-filter excludes that document because its store_id value is an array, not one of the scalar constants. See MongoDB’s aggregation $in reference for how it compares values.
Nested paths also preserve arrays. If a document contains items: [{ sku: 'sku-a' }, { sku: 'sku-b' }], the path $$doc.items.sku produces an array of SKU values. It does not match $eq: ['$$doc.items.sku', 'sku-a']. The supported pre-filter operators cannot express “any array element matches”; use a scalar source field for that condition.
Numbers and Other Types
MongoDB compares numbers by value across BSON numeric types. For example,$eq: ['$$doc.quantity', 5] matches a quantity stored as Int32, Int64, Double, or Decimal128 when its value is 5. Using { $numberLong: '5' } as the filter constant does not restrict matching to Int64 fields.
Other types are not converted to numbers during comparison:
Keep the source field’s type consistent with the filter constant. For example, compare an ObjectId field against an EJSON
$oid constant, not its hexadecimal string. See MongoDB’s BSON comparison rules.
Collection Names and Wildcards
Eachsource_table_options key identifies a collection. Use collection, database.collection, or connection.database.collection. Unqualified names use the connection’s default database. The default connection tag is default.
A final % matches a collection-name prefix. Database wildcards are not supported. For example:
mongodb_filter_expression: disabled to exclude a collection from a wildcard filter. An empty options object ({}) inherits the matching wildcard filter.
These entries configure collections already selected by your Sync Streams queries. They do not cause additional collections to replicate.
Snapshot Indexes
The Service does not create indexes. Without a suitable index, MongoDB can still scan many or all source documents during the snapshot, even though excluded documents do not enter bucket storage. Create indexes on the filtered fields with_id as the final key. Use collation: { locale: 'simple' }, because filtered snapshots use this collation. For example, a filter on store_id can use:
$orneeds a suitable index for every branch. An unindexed branch can cause a collection scan for the whole filter.$andcan use an index on one term. Prefer the most selective term. For an$andof equality conditions, a compound index on those fields followed by_idcan narrow the scan further.
_id avoids that repeated work. MongoDB may still choose an _id index scan when a filter matches a large fraction of the collection.
For index options, see MongoDB’s createIndex() reference.
Changes to Filtered Documents
During replication, the Service keeps stored data consistent with the pre-filter:
Pre-filtering reduces stored data, but excluded changes still have some network and processing cost. MongoDB sends compact progress events for excluded changes so that the Service can advance its recovery position through a backlog of excluded writes.