Portal Community

When to Use

Configuration

Connection

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

Operation

FieldRequiredDescription
QueryOptionalFilter to select documents to update. Default {} matches all documents in the collection — use with extreme caution. Use precise filters targeting indexed fields. Example: {"status": "packed", "shipDate": {"$lt": "{{ $now }}"}}.
UpdateOptionalUpdate operators to apply. Must use MongoDB update operator syntax. Common operators: $set (assign fields), $unset (remove fields), $inc (increment), $push (append to array), $pull (remove from array), $addToSet (append if unique), $currentDate (set to current date). Example: {"$set": {"status": "delayed"}, "$currentDate": {"updatedAt": true}}.
UpsertOptionalDefault false. When true, if no documents match the Query, a new document is created by merging the filter fields with the update expression. Useful for counter or preference documents that should exist after first update.
UpdateManyOptionalDefault true. When true, all documents matching the filter are updated. When false, only the first matching document (in natural collection order) is updated. Set to false for single-record updates where you want to guarantee only one document is affected.
Default UpdateMany is true. With an empty Query: {} and UpdateMany: true, this operation updates every document in the collection. Always specify a precise query filter before enabling UpdateMany on production collections. Test query selectivity in a staging environment first.

Sample Configuration

Bulk-transition all overdue "packed" orders to "delayed" status, updating the delayReason and updatedAt fields:

{
  "resource": "document",
  "operation": "update",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "ecommerce",
  "Collection": "orders",
  "Query": {
    "status": "packed",
    "scheduledShipDate": { "$lt": "{{ $now }}" },
    "tenantId": "{{ $json.tenantId }}"
  },
  "Update": {
    "$set": {
      "status": "delayed",
      "delayReason": "carrier_capacity",
      "updatedAt": "{{ $now }}"
    },
    "$push": {
      "statusHistory": {
        "from": "packed",
        "to": "delayed",
        "changedAt": "{{ $now }}",
        "reason": "carrier_capacity"
      }
    }
  },
  "Upsert": false,
  "UpdateMany": true
}

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
matchedCountintegerNumber of documents that matched the query filter. May be greater than modifiedCount when some matched documents already had the target field value.
modifiedCountintegerNumber of documents actually modified. A document matches but is not modified if the update would produce no change (e.g. $set to the same value).
upsertedCountintegerNumber of documents inserted via upsert. 0 when no upsert occurred. 1 when an upsert created a new document.
upsertedIdstringThe MongoDB ObjectID of the upserted document. Empty string when no upsert occurred.
statusstringAlways "success".
resourcestringAlways "document".
operationstringAlways "update".

Sample Output

{
  "matchedCount": 47,
  "modifiedCount": 47,
  "upsertedCount": 0,
  "upsertedId": "",
  "status": "success",
  "resource": "document",
  "operation": "update"
}

Expression Reference

ExpressionReturnsDescription
{{ $output.BulkUpdateOrders.matchedCount }}integerTotal documents matched by the query filter. Compare to modifiedCount to detect skipped documents.
{{ $output.BulkUpdateOrders.modifiedCount }}integerActual number of documents modified. Use in downstream IfCondition: branch on modifiedCount == 0 to handle no-op updates.
{{ $output.BulkUpdateOrders.upsertedCount }}integerCount of upserted documents. 0 means no new documents were created.
{{ $output.BulkUpdateOrders.upsertedId }}stringID of the upserted document — use to reference the newly created record in subsequent steps.
{{ $output.BulkUpdateOrders.status }}stringConfirm "success" for conditional logic.

Node Policies & GuardRails

PolicyRecommendation
Credential storageAlways reference ConnectionUri from BizFirst Credentials Manager. Never embed raw URIs with credentials in workflow node fields.
Query filter disciplineNever use an empty Query: {} with UpdateMany: true in production without a deliberate scope. Always include tenant, status, or date range constraints to scope the update to the intended record set.
Test with UpdateMany: false firstWhen building a new bulk update workflow, test the query filter with UpdateMany: false in a staging environment. Confirm the matched document is the expected one before switching to UpdateMany: true.
Index query fieldsAll fields in the Query should have supporting indexes. UpdateMany on large unindexed collections causes full collection scans and may exceed operation time limits.
Multi-tenancyAlways include tenantId in the Query to prevent cross-tenant updates in shared collections.
modifiedCount vs matchedCountIf matchedCount > modifiedCount, some documents were already in the target state. This is normal. If matchedCount == 0, no documents matched — branch to handle this in an IfCondition node rather than silently continuing.
Upsert uniquenessWhen Upsert: true, ensure the query filter uniquely identifies a document to prevent unintended new document creation when used with UpdateMany.
Timestamp all updatesAlways include "$currentDate": {"updatedAt": true} or "$set": {"updatedAt": "{{ $now }}"} in every update to maintain an audit-compatible modification timestamp on each document.

Workflow Examples

Example 1 — Bulk Feature Flag Rollout

{
  "resource": "document",
  "operation": "update",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "platform",
  "Collection": "users",
  "Query": { "planTier": "enterprise", "tenantId": "{{ $json.tenantId }}" },
  "Update": {
    "$set": {
      "featureFlags.advancedReporting": true,
      "featureFlags.bulkExport": true,
      "updatedAt": "{{ $now }}"
    }
  },
  "Upsert": false,
  "UpdateMany": true
}

Example 2 — Single Product Stock Decrement

{
  "resource": "document",
  "operation": "update",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "ecommerce",
  "Collection": "products",
  "Query": { "sku": "{{ $json.sku }}", "stockQty": { "$gte": "{{ $json.orderedQty }}" } },
  "Update": {
    "$inc": { "stockQty": "{{ $json.orderedQty | multiply(-1) }}" },
    "$set": { "lastSoldAt": "{{ $now }}" }
  },
  "Upsert": false,
  "UpdateMany": false
}

Example 3 — Subscription Plan Migration

{
  "resource": "document",
  "operation": "update",
  "ConnectionUri": "{{ $credentials.mongodbAtlas }}",
  "Database": "billing",
  "Collection": "subscriptions",
  "Query": {
    "planId": "LEGACY_STARTER_V1",
    "status": "active",
    "tenantId": "{{ $json.tenantId }}"
  },
  "Update": {
    "$set": { "planId": "STARTER_V2", "updatedAt": "{{ $now }}" },
    "$push": {
      "planHistory": {
        "fromPlan": "LEGACY_STARTER_V1",
        "toPlan": "STARTER_V2",
        "migratedAt": "{{ $now }}",
        "reason": "plan_discontinuation"
      }
    }
  },
  "Upsert": false,
  "UpdateMany": true
}