Skip to content

Mongo Collation Support - #14188

Merged
italojs merged 17 commits into
meteor:release-3.5from
mvogttech:mongo-collation-support
Apr 27, 2026
Merged

italojs merged 17 commits into
meteor:release-3.5from
mvogttech:mongo-collation-support

Conversation

@mvogttech

@mvogttech mvogttech commented Mar 3, 2026

Copy link
Copy Markdown
Collaborator
  • Add full MongoDB collation support to find, findOne, findOneAsync, and observeChanges
  • Implement collation-aware string comparison in Minimongo using Intl.Collator, so client and server behave identically
  • Compatible with oplog-tailing — no fallback to polling required

Motivation

Previously, collation options passed to Collection.find() were silently dropped by the mongo driver's cursor whitelist, and Minimongo had no concept of locale-aware string comparison at all. This forced workarounds like generateCasePermutationsForString, which builds 16-clause $or queries for case-insensitive lookups.

Note: This is how I found minimongo/mongo were missing collation support. I wanted to modernize accounts-* packages and ran into generateCasePermutationsForString -- which is a workaround that exists since MongoDB v2.

With this PR, a simple {collation: {locale: 'en', strength: 2}} option enables case-insensitive matching on both client and server, using MongoDB's native collation on the server and Intl.Collator in Minimongo. Since Minimongo now understands collation, the oplog observe driver can correctly filter oplog events for collation queries without falling back to polling.

Changes

Minimongo (packages/minimongo/)

File Change
matcher.js Matcher accepts collation param, creates Intl.Collator via _createCollator. Threads collator through _cmp and _equal for all string comparisons. Scalar _id fast path falls through to document selector compilation when collation is active.
common.js equalityElementMatcher and inequality operators ($gt, $gte, $lt, $lte, $eq, $ne, $in, $nin) accept and pass through the collator.
sorter.js Sorter accepts collation param, passes collator to _cmp in _keyFieldComparator.
cursor.js Passes options.collation to Matcher and Sorter. Skips _selectorId fast path when collation is present (direct IdMap.get is not collation-aware).

Mongo driver (packages/mongo/)

File Change
mongo_connection.js Added collation to the mongoOptions whitelist in _createAsynchronousCursor. Passes cursorDescription.options.collation to Minimongo.Matcher and Minimongo.Sorter in _observeChanges.
cursor_description.ts Added CollationOptions interface and collation? field to CursorOptions.
package.js Registered collation_tests.js in onTest.

Documentation

File Change
collection/methods_sync.js Added @param options.collation to find() and findOne() JSDoc.
collection/methods_async.js Added @param options.collation to findOneAsync() JSDoc.
docs/source/api/collections.md Added paragraph explaining collation support with usage example.
packages/minimongo/README.md Added collation to the feature list.

Collation option mapping

MongoDB collation options are mapped to Intl.Collator as follows:

MongoDB Intl.Collator Effect
strength: 1 sensitivity: 'base' Ignore case and accents (cafe = Café)
strength: 2 sensitivity: 'accent' Case-insensitive (alice = Alice, cafecafé)
strength: 3 (default) sensitivity: 'variant' Exact match (default behavior)
strength: 1 + caseLevel: true sensitivity: 'case' Case-sensitive but accent-insensitive
numericOrdering: true numeric: true '2' sorts before '10'
caseFirst: 'upper'/'lower' caseFirst: 'upper'/'lower' Uppercase or lowercase first in sort

Usage example

// Case-insensitive find
const users = Users.find(
  { email: 'Alice@Example.COM' },
  { collation: { locale: 'en', strength: 2 } }
).fetch();

// Case-insensitive sort
const sorted = Posts.find(
  {},
  { collation: { locale: 'en', strength: 2 }, sort: { title: 1 } }
).fetch();

// Create a collation-backed index for efficient queries
await Users.createIndexAsync(
  { email: 1 },
  { collation: { locale: 'en', strength: 2 } }
);

@netlify

netlify Bot commented Mar 3, 2026

Copy link
Copy Markdown

Deploy Preview for v3-meteor-api-docs canceled.

Name Link
🔨 Latest commit c8df2eb
🔍 Latest deploy log https://app.netlify.com/projects/v3-meteor-api-docs/deploys/69ef6bfaaa7ad90008cef1da

@netlify

netlify Bot commented Mar 3, 2026

Copy link
Copy Markdown

Deploy Preview for v3-migration-docs canceled.

Name Link
🔨 Latest commit 329f303
🔍 Latest deploy log https://app.netlify.com/projects/v3-migration-docs/deploys/69aeefa33fbafd0008da6dc7

@mvogttech
mvogttech marked this pull request as ready for review March 5, 2026 16:36
Comment thread packages/mongo/tests/collation_tests.js
@mvogttech

Copy link
Copy Markdown
Collaborator Author

@italojs italojs added this to the Release 3.5 milestone Mar 9, 2026
@italojs
italojs changed the base branch from devel to release-3.5 March 9, 2026 18:42
@mvogttech

Copy link
Copy Markdown
Collaborator Author

@italojs - Do you want me to resolve the conflicts?

@italojs

italojs commented Mar 16, 2026

Copy link
Copy Markdown
Member

@mvogttech feel free to handle it. thanks ;)

Comment thread packages/mongo/cursor_description.ts
Comment thread packages/mongo/tests/collation_tests.js Outdated

@radekmie radekmie left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard for me to tell, whether Intl.Collator and MongoDB's collation are truly compatible, but overall it looks correct. I'm only thinking about making some of the tests run both on the client and the server to check for that.

Comment thread packages/minimongo/matcher.js Outdated
Comment thread packages/minimongo/matcher.js
@mvogttech

Copy link
Copy Markdown
Collaborator Author

It's hard for me to tell, whether Intl.Collator and MongoDB's collation are truly compatible, but overall it looks correct. I'm only thinking about making some of the tests run both on the client and the server to check for that.

The client+server test parity should help catch any Intl.Collator vs MongoDB divergence — both sides now run the same find, sort, inequality, and strength-1 tests against the same data. If we find edge cases where they diverge, we can add targeted tests for those.

Based on my research Mongo's collation is based on Int.Collator. They are very similar.

Comment thread packages/minimongo/matcher.js Outdated

@radekmie radekmie left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I'm concerned, this one looks solid.

@italojs
italojs merged commit cb0933a into meteor:release-3.5 Apr 27, 2026
26 of 29 checks passed
italojs added a commit that referenced this pull request Apr 29, 2026
…ort"

This reverts commit cb0933a, reversing
changes made to 70be781.
italojs added a commit that referenced this pull request May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants