Portal Community

When to Use

Full document replacement. Unlike findOneAndUpdate (which applies partial operators), this operation replaces the entire document body. All existing fields not present in the Replacement object will be permanently deleted. The original _id is preserved automatically. Use document/findOneAndUpdate with $set when you want to update specific fields without disturbing others.

Configuration

Connection

FieldRequiredDescription
ConnectionUriRequiredMongoDB connection string. Reference via {{ $credentials.mongodbAtlas }}.
DatabaseRequiredTarget database name.
CollectionRequiredTarget collection name.

Operation

FieldRequiredDescription
QueryOptionalFilter to locate the document to replace. Default {} matches the first document. Use a unique identifier (e.g. {"externalId": "PROD-001"} or {"_id": "..."}) to target the correct document. Supports MongoDB query operators.
ReplacementOptionalThe complete new document body as a JSON object. Default {} replaces all fields with an empty document. Do not include _id — MongoDB automatically preserves the original _id. Do not use update operators here — this is a plain document, not an operator expression. Example: {"name": "Widget Pro", "price": 49.99, "category": "tools", "updatedAt": "{{ $now }}"}.
UpsertOptionalDefault false. When true, if no document matches the Query, MongoDB inserts the Replacement document as a new record. Enables idempotent create-or-replace patterns.
ReturnNewDocumentOptionalDefault false. When false, the returned document is the original document before replacement — use this for audit/rollback capture. When true, the returned document is the replacement document after the write.

Sample Configuration

Replace a product catalogue entry with the latest supplier data, upserting if not yet present, and return the old document for change-tracking:

{
  "resource": "document",
  "operation": "find-one-and-replace",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "catalog",
  "Collection": "products",
  "Query": {
    "externalId": "{{ $json.supplierProductId }}",
    "tenantId": "{{ $json.tenantId }}"
  },
  "Replacement": {
    "externalId": "{{ $json.supplierProductId }}",
    "tenantId": "{{ $json.tenantId }}",
    "name": "{{ $json.productName }}",
    "sku": "{{ $json.sku }}",
    "category": "{{ $json.category }}",
    "price": "{{ $json.price }}",
    "currency": "USD",
    "stockQty": "{{ $json.stockQty }}",
    "images": "{{ $json.images }}",
    "specifications": "{{ $json.specs }}",
    "lastSyncedAt": "{{ $now }}"
  },
  "Upsert": true,
  "ReturnNewDocument": false
}

Validation Errors

ErrorCause
connectionUri is requiredConnectionUri is empty or not provided.
database is requiredDatabase field is empty.
collection is requiredCollection field is empty.

Output — Success Port

FieldTypeDescription
foundbooleantrue if a document was found and replaced. false if no match was found (and Upsert is false, meaning no write occurred). When Upsert: true and no match exists, found is false but a new document was inserted.
documentobjectWhen ReturnNewDocument: false: the original document before replacement. When ReturnNewDocument: true: the replacement document as written. Returns {} when found is false and no upsert occurred.
statusstringAlways "success".
resourcestringAlways "document".
operationstringAlways "find-one-and-replace".

Sample Output

Output when ReturnNewDocument: false — returns the document as it was before replacement:

{
  "found": true,
  "document": {
    "_id": "6651a3f2c4e8b9d0a1f23456",
    "externalId": "PROD-9821",
    "tenantId": "tenant_acme",
    "name": "Widget Pro v1",
    "sku": "WGT-PRO-001",
    "category": "tools",
    "price": 44.99,
    "currency": "USD",
    "stockQty": 142,
    "lastSyncedAt": "2024-11-01T08:00:00.000Z"
  },
  "status": "success",
  "resource": "document",
  "operation": "find-one-and-replace"
}

Expression Reference

ExpressionReturnsDescription
{{ $output.ReplaceProduct.found }}booleanWhether a matching document was found. Branch in IfCondition to detect new inserts (upsert path) vs replacements.
{{ $output.ReplaceProduct.document }}objectThe full document returned (pre- or post-replacement based on ReturnNewDocument).
{{ $output.ReplaceProduct.document._id }}stringThe preserved MongoDB _id of the document.
{{ $output.ReplaceProduct.document.name }}stringA specific field from the returned document.
{{ $output.ReplaceProduct.document.price }}numberNumeric field — the old price (if ReturnNewDocument: false) for change-detection comparisons.
{{ $output.ReplaceProduct.document.lastSyncedAt }}stringTimestamp field on the returned document.

Node Policies & GuardRails

PolicyRecommendation
Credential storageAlways reference ConnectionUri from BizFirst Credentials Manager. Never embed raw connection strings in workflow configuration.
Understand full replacementThis operation erases all fields not in Replacement. Before using it, verify there are no system-managed fields (audit history arrays, internal flags) that should be preserved. If partial field updates are needed, use document/findOneAndUpdate with $set instead.
Preserve the _idDo not include _id in the Replacement document. MongoDB preserves the original _id automatically. Including _id with a different value raises an immutable field error.
Capture old document for auditUse ReturnNewDocument: false and insert a follow-up document/insert step to write the captured old document to a change_history collection for full audit trail coverage.
Upsert with unique indexWhen Upsert: true, ensure the Query filter targets fields covered by a unique index to prevent duplicate inserts under concurrent execution.
Multi-tenant isolationAlways include tenantId in the Query filter. Replacing a document from the wrong tenant is irreversible.
Index the query filterThe Query should target indexed fields. findOneAndReplace performs a collection scan when no index supports the filter, which degrades under concurrent load.
Error port handlingConnect the error port to a notification node. A failed replace on a critical document (e.g. config, active session) should alert immediately rather than silently failing.

Workflow Examples

Example 1 — Idempotent Product Sync from External Feed

{
  "resource": "document",
  "operation": "find-one-and-replace",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "catalog",
  "Collection": "products",
  "Query": { "externalId": "{{ $json.productId }}", "tenantId": "{{ $json.tenantId }}" },
  "Replacement": {
    "externalId":  "{{ $json.productId }}",
    "tenantId":    "{{ $json.tenantId }}",
    "name":        "{{ $json.name }}",
    "price":       "{{ $json.price }}",
    "category":    "{{ $json.category }}",
    "inStock":     "{{ $json.inStock }}",
    "syncedAt":    "{{ $now }}"
  },
  "Upsert": true,
  "ReturnNewDocument": false
}

Example 2 — Application Config Snapshot Replacement

{
  "resource": "document",
  "operation": "find-one-and-replace",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "platform",
  "Collection": "app_configs",
  "Query": { "configKey": "feature_flags", "environment": "production" },
  "Replacement": {
    "configKey":     "feature_flags",
    "environment":   "production",
    "flags":         "{{ $json.newFeatureFlags }}",
    "updatedBy":     "{{ $json.updatedByUserId }}",
    "updatedAt":     "{{ $now }}",
    "version":       "{{ $json.configVersion }}"
  },
  "Upsert": false,
  "ReturnNewDocument": false
}

Example 3 — Workflow State Checkpoint

{
  "resource": "document",
  "operation": "find-one-and-replace",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "workflow_engine",
  "Collection": "execution_state",
  "Query": { "workflowRunId": "{{ $execution.id }}" },
  "Replacement": {
    "workflowRunId": "{{ $execution.id }}",
    "workflowId":    "{{ $workflow.id }}",
    "currentStage":  "{{ $json.currentStage }}",
    "stageData":     "{{ $json.stagePayload }}",
    "resumeToken":   "{{ $json.resumeToken }}",
    "checkpointAt":  "{{ $now }}"
  },
  "Upsert": true,
  "ReturnNewDocument": true
}