When to Use
- Order status transitions: In a fulfilment workflow, atomically move an order from
status: "pending" to status: "processing" and retrieve the updated document — including shipping address and line items — in one step. Without the atomic guarantee, a race condition between two parallel executions could claim the same order twice.
- Distributed task claiming: A processing worker workflow queries for the next available task (
status: "queued"), sets it to status: "in_progress", and stamps the worker ID and started timestamp. The atomic find-and-update ensures no two workers claim the same task, even under concurrent execution.
- Loyalty point accumulation: When a purchase event fires, find the customer's loyalty account document and use
$inc to atomically add earned points. Set ReturnNewDocument: true to get the updated balance immediately for the confirmation message without a separate find query.
- Subscription renewal tracking: When a payment is processed, find the subscription document by
subscriptionId, update renewedAt and nextRenewalDate using $set, and push the payment reference onto a paymentHistory array using $push. Return the new document to generate the renewal confirmation.
- Upsert-based session management: For a user session store, use find-one-and-update with
Upsert: true on sessionId to either refresh an existing session (update lastActive) or create a new session document if none exists — all in one operation.
Configuration
Connection
| Field | Required | Description |
ConnectionUri | Required | MongoDB connection string. Reference via {{ $credentials.mongodbAtlas }}. |
Database | Required | Target database name. |
Collection | Required | Target collection name. |
Operation
| Field | Required | Description |
Query | Optional | Filter to locate the document to update. Default {} matches the first document in natural order. Use a precise filter (e.g. unique ID or indexed status field) to target the correct document. Example: {"orderId": "ORD-001", "status": "pending"}. |
Update | Optional | Update operators to apply. Default {} results in no change. Must use MongoDB update operators — do not pass a replacement document here (use findOneAndReplace for full replacement). Supported operators: $set, $unset, $inc, $push, $pull, $addToSet, $currentDate. Example: {"$set": {"status": "processing"}, "$currentDate": {"updatedAt": true}}. |
Upsert | Optional | Default false. When true, if no document matches the Query, MongoDB creates a new document by merging the filter fields with the update document. Use for create-or-update patterns such as session management or preference upserts. |
ReturnNewDocument | Optional | Default false. When false, the returned document is the state of the record before the update — useful for capturing what changed. When true, the returned document reflects the state after the update — useful for getting the new computed value (e.g. updated point balance or refreshed timestamp). |
Update operators only. The
Update field must use MongoDB update operators (
$set,
$inc, etc.). Passing a plain document object without operators will result in an error. To fully replace a document, use
document/findOneAndReplace instead.
Sample Configuration
Atomically claim a queued background job for processing and return the updated document with worker attribution:
{
"resource": "document",
"operation": "find-one-and-update",
"ConnectionUri": "{{ $credentials.mongodbAtlas }}",
"Database": "jobs",
"Collection": "task_queue",
"Query": {
"status": "queued",
"jobType": "{{ $json.jobType }}",
"tenantId": "{{ $json.tenantId }}"
},
"Update": {
"$set": {
"status": "in_progress",
"workerId": "{{ $execution.id }}",
"startedAt": "{{ $now }}"
}
},
"Upsert": false,
"ReturnNewDocument": true
}
Validation Errors
| Error | Cause |
connectionUri is required | ConnectionUri is empty or not provided. |
database is required | Database field is empty. |
collection is required | Collection field is empty. |
Output — Success Port
| Field | Type | Description |
found | boolean | true if a document matched the query and was updated. false if no match was found (and Upsert is false). |
document | object | The document before the update (ReturnNewDocument: false) or after the update (ReturnNewDocument: true). Returns an empty object {} when found is false. |
status | string | Always "success". |
resource | string | Always "document". |
operation | string | Always "find-one-and-update". |
Sample Output
{
"found": true,
"document": {
"_id": "6651a3f2c4e8b9d0a1f23456",
"jobId": "JOB-7821",
"jobType": "invoice_generation",
"status": "in_progress",
"workerId": "exec_a7f3d091",
"startedAt": "2024-11-15T09:22:44.000Z",
"tenantId": "tenant_acme",
"payload": {
"invoiceMonth": "2024-10",
"customerId": "CUST-10293"
}
},
"status": "success",
"resource": "document",
"operation": "find-one-and-update"
}
Expression Reference
| Expression | Returns | Description |
{{ $output.ClaimTask.found }} | boolean | Whether a document was found. Use in IfCondition: branch on found == false to handle "no available task" scenarios. |
{{ $output.ClaimTask.document }} | object | The full document (pre- or post-update depending on ReturnNewDocument). |
{{ $output.ClaimTask.document.jobId }} | string | Access a top-level field on the returned document. |
{{ $output.ClaimTask.document.payload.customerId }} | string | Access a nested field within the returned document. |
{{ $output.ClaimTask.document.status }} | string | Confirm the new status value when ReturnNewDocument: true. |
{{ $output.ClaimTask.document._id }} | string | The MongoDB document ID — use to reference or update this document in subsequent nodes. |
Node Policies & GuardRails
| Policy | Recommendation |
| Credential storage | Always reference ConnectionUri from Credentials Manager. Never embed connection strings with passwords in workflow node configuration. |
| Use update operators only | The Update field must contain MongoDB update operators such as $set, $inc, or $push. Passing a plain replacement object will cause a MongoDB driver error. Use document/findOneAndReplace for full document replacement. |
| Handle found = false | Always connect an IfCondition node after this operation that checks found == false. A no-match result silently returns an empty document, which causes null-reference errors in downstream nodes that assume a document was found. |
| Index the query filter | The Query filter should target indexed fields for performance. For task queue patterns, index on {status: 1, jobType: 1}. Unindexed findOneAndUpdate operations scan the entire collection. |
| Upsert safety | When Upsert: true, ensure the Query filter contains enough specificity to avoid accidentally creating duplicate documents. Consider unique indexes on the query fields to enforce at the database layer. |
| Multi-tenancy | Always include tenantId in the Query filter to prevent cross-tenant document mutation in shared collections. |
| Timestamp updates | Use $currentDate or "$set": {"updatedAt": "{{ $now }}"} to track when documents were last modified. This is essential for audit trails and debugging workflow execution issues. |
| ReturnNewDocument choice | Use ReturnNewDocument: false (default) when you need to capture the pre-update state for audit logging. Use ReturnNewDocument: true when the downstream step needs the result of computed changes like $inc. |
Workflow Examples
Example 1 — Atomic Order Status Transition
{
"resource": "document",
"operation": "find-one-and-update",
"ConnectionUri": "{{ $credentials.mongodbAtlas }}",
"Database": "ecommerce",
"Collection": "orders",
"Query": {
"orderId": "{{ $json.orderId }}",
"status": "pending",
"tenantId": "{{ $json.tenantId }}"
},
"Update": {
"$set": {
"status": "processing",
"processedAt": "{{ $now }}",
"processedBy": "{{ $execution.id }}"
}
},
"Upsert": false,
"ReturnNewDocument": true
}
Example 2 — Loyalty Points Increment
{
"resource": "document",
"operation": "find-one-and-update",
"ConnectionUri": "{{ $credentials.mongodbAtlas }}",
"Database": "loyalty",
"Collection": "accounts",
"Query": {
"customerId": "{{ $json.customerId }}"
},
"Update": {
"$inc": { "pointsBalance": "{{ $json.earnedPoints }}" },
"$push": {
"transactions": {
"type": "earn",
"points": "{{ $json.earnedPoints }}",
"orderId": "{{ $json.orderId }}",
"timestamp": "{{ $now }}"
}
}
},
"Upsert": true,
"ReturnNewDocument": true
}
Example 3 — Session Refresh (Upsert Pattern)
{
"resource": "document",
"operation": "find-one-and-update",
"ConnectionUri": "{{ $credentials.mongodbAtlas }}",
"Database": "auth",
"Collection": "sessions",
"Query": {
"sessionId": "{{ $json.sessionId }}"
},
"Update": {
"$set": {
"userId": "{{ $json.userId }}",
"lastActive": "{{ $now }}",
"userAgent": "{{ $json.userAgent }}"
}
},
"Upsert": true,
"ReturnNewDocument": true
}