Life ConnectLife Connect
Wiki index
Architecture
Services
UI
Concepts
Runbooks
Infra
Swagger Docs
GitHub
Wiki index
Architecture
Services
UI
Concepts
Runbooks
Infra
Swagger Docs
GitHub
  • Runbooks

    • Run the local stack
    • Deploy a PR preview
    • Provision a new environment
Last updated 2026-07-22

Local Atlas Search ($search)

AI-generated content

This document was generated by an AI assistant. Verify accuracy before relying on the details.

The packages/data search pipelines (person / part / sale / contract / ticket typed search) emit an Atlas Search $search stage. That stage is Atlas-only: against the default local mongo:7 community server it fails with "$search stage is only allowed on MongoDB Atlas". The adb-parts Worker maps that to an explicit 501 so it reads as a limitation, not a code bug; persons / contracts / tickets currently surface a raw 500 for the same reason.

This runbook makes $search work locally by swapping the plain mongod for MongoDB's all-in-one mongodb-atlas-local image (mongod + mongot) and creating the search indexes from the definitions already checked into the repo.

TL;DR

cd infra
make up-search          # infra stack on mongodb-atlas-local (first run pulls ~670 MB)
make seed               # only if switching from a fresh/plain-mongo run
make search-indexes     # create the Atlas Search indexes (idempotent)

Then run the CF stack as usual (pnpm dev + adb-ui). Typed search now returns results instead of a 501/500.

Which image, and why

ImageWhat it isUse it?
mongodb/mongodb-atlas-searchThe bare mongot search process (a sidecar). Wiring it to a community mongod needs a shared keyfile + mongotHost/searchIndexManagementHostAndPort setParameters and is unsupported before MongoDB 8.2.No
mongodb/mongodb-atlas-localAll-in-one: mongod + mongot as one self-initialising single-node replica set. MongoDB's documented path for local Atlas Search. Publishes a 7.0 track, native arm64.Yes

We pin mongodb/mongodb-atlas-local:7.0.34 — same server major as the default mongo:7 (so a seeded /data/db stays compatible), and a stable tag rather than preview (whose Community mongot has an incomplete $listSearchIndexes, which the index bootstrap's idempotency check relies on).

How it is wired

  • infra/docker/compose.search.yaml — an overlay on compose.yaml. It swaps the mongo image, pins hostname: mongo (so the replica-set member is advertised as mongo:27017, matching what the Spring services resolve), clears the base mongod --replSet rs0 command so atlas-local's own entrypoint runs, and adds the configdb + mongot data volumes atlas-local needs. make up-search layers it via -f compose.yaml -f compose.search.yaml (which disables the auto-loaded compose.override.yaml).
  • create-search-indexes.sh — a one-shot sidecar (gated behind the indexes compose profile so it never auto-runs). It reads the seven definitions in adb-infrastructure/mongodb-atlas/atlas-cli/search/indexes/*.json, reshapes each Atlas-CLI envelope { name, database, collectionName, mappings, analyzers } into the createSearchIndex(name, { mappings, analyzers }) mongosh helper, and applies it. It is idempotent: it skips an index that already exists and a collection not yet seeded, and retries per index (mongot can lag mongod readiness).

The seven indexes and their collections:

DefinitionIndexCollectionUsed by the CF port?
persons-search-index.jsonadb-persons-…adb-persons.persons✅ person search
parts-search-index.jsonadb-parts-…adb-parts.parts✅ part search
parts-sales-search-index.jsonadb-parts-sales-…adb-parts.sales✅ sale search
contracts-search-index.jsonadb-contracts-…adb-contracts.contracts✅ contract search
tickets-search-index.jsonadb-tickets-…adb-tickets.tickets✅ ticket search
views-parts-search-index.jsonadb-views-parts-…adb-views.parts❌ CF port uses $regex, not $search
invoices-search-index.jsonadb-accounting-invoices-…adb-accounting.invoices❌ CF invoice search drops the $search stage (TODO parity)

The last two are created for fidelity with real Atlas but no ported code queries them yet.

The analyzer (what "case-insensitive-search-regex" means)

Every index uses one custom analyzer, search_keyword_lowercaser:

  • tokenizer keyword — the entire field value is a single token, so only wildcard-wrapped patterns (*term*) match a substring;
  • lowercase token filter — case-insensitive;
  • a mapping charFilter — a hand-written accent-folding table (é→e, ç→c, …).

So it is a LIKE-style, accent- and case-insensitive match, not true full-text search — hence the name.

The CF broker needs no change

The broker's local services/mongo-broker/.dev.vars already connects with directConnection=true (mongodb://host.docker.internal:27018/?directConnection=true), which skips topology discovery — so it does not care how atlas-local advertises its replica-set member. atlas-local keeps the same 27018:27017 host port. Nothing to edit.

Caveats

  • Not read-your-writes. mongot refreshes its Lucene index ~1s after a write, so a document created and immediately searched may not appear yet.
  • Parity is only as good as the checked-in definitions. The seven JSONs have a single commit in history (6376e7e Convert submodules to monorepo) and have never been reconciled against the live Atlas cluster. If prod's indexes have since drifted, local results will differ, and nothing in the test suite or CI can catch it — the packages/data search tests assert pipeline shape against a fake client, never a result. Treat local $search as a good functional check, not a parity oracle.
  • Two searches still won't work locally even with this stack: the adb-views parts search (the properties list — the CF port uses $regex) and adb-accounting invoice search (the CF port drops the $search stage). These are distinct gaps, not fixed here.
  • Image pull may hang behind Cloudflare WARP. If make up-search stalls on the image pull, a busy-looping WARP daemon is poisoning Docker's registry path — Quit WARP (not just Disconnect) and restart Docker Desktop, then retry. This is why the compose overlay was authored but could not be validated against a live pull.
  • If the container fails to boot, the most likely culprit is the command: [] reset in the overlay — remove that line so atlas-local uses its image-default CMD, and retry.

Making it the default (once validated)

make up-search is deliberately opt-in so the known-good mongo:7 path stays the default. Once the atlas-local image is confirmed working on your machine, promoting it to the default is a small change: fold the mongo service block from compose.search.yaml into compose.yaml and drop the now-redundant mongo-init replica-set bootstrap (atlas-local self-initialises its replica set).

Edit this page
Last Updated:
Contributors: Grégory Horion