Skip to Content

Odoo Upsert

The Odoo Upsert transform is a specialized output operation that creates or updates records in Odoo. It intelligently determines whether to INSERT a new record or UPDATE an existing one by comparing lookup keys. This transform is essential for synchronizing data from external sources (HubSpot, Shopify, etc.) into Odoo.

Icon

Usage

The core parameters define how records are created/updated in Odoo:

  • Transform Name: Unique identifier for this transform (e.g., "upsert-contacts"). Used for logging and error tracking.

  • Odoo Connection: Configured Odoo server connection. Dropdown shows available connections (e.g., "odoo-production").

  • Odoo Model: Target Odoo business object (e.g., res.partner for contacts, product.product for products, crm.lead for leads).

  • Batch Size: Number of records to process per API batch (default: 100, range: 1-1000). Higher = faster but more memory.

  • Return result info (action + ID): Checkbox - when enabled, transform returns action (created/updated) and Odoo record ID for each record.

Lookup Keys (Used to Find Existing Records)

Lookup Keys determine whether a record already exists in Odoo. If a match is found, the record is UPDATED. If no match is found, a new record is CREATED. You can define multiple keys (AND logic).

  1. How it works:

  • For each incoming record, Upsert searches Odoo using the Lookup Keys

  • If Odoo finds a record matching ALL keys → UPDATE that record

  • If Odoo finds NO match → CREATE a new record

Lookup Key Configuration
  • Stream Field: Field from your input data (e.g., email, hubspot_id, sku)

  • Comparator: Comparison operator: "=" (equals), "!=" (not equals), "like", etc. Usually "=" for matching.

  • Odoo Field: The Odoo field to compare against (e.g., email, external_id, default_code)

  1. Example Lookup Key:

  • Stream Field: email

  • Comparator: =

  • Odoo Field: email

  • Logic: "Find record where Odoo email = input email"

  1. This finds existing contacts by email. If found, updates them. If not found, creates new contact.

Field Mappings (Values to Insert/Update)

Field Mappings define which data from your input stream should be written to which Odoo fields. Only mapped fields are updated - other Odoo fields remain unchanged.

  1. Field Mapping Configuration:

  • Stream Field: Field from your input data (e.g., first_name, email, phone)

  • Odoo Field: Target Odoo field where data should be written (e.g., name, email, phone)

  • Default Value: Value to use if Stream Field is NULL/empty (optional)

  • Required: Checkbox - if checked, Odoo will reject records if this field is empty

  1. Buttons:

  • Get Odoo Fields - Automatically populates available Odoo fields for the selected model

  • Edit Mapping - Opens advanced mapping editor for complex transformations

Upsert Data Flow

How Odoo Upsert processes data:

  • 1. Read incoming record from stream

  • 2. Apply Lookup Keys to search Odoo for existing record

  • 3. If record found → UPDATE with values from Field Mappings

  • 4. If record not found → CREATE new record with values from Field Mappings

  • 5. Return result (if enabled): action (created/updated) + Odoo record ID

  • 6. Move to next record and repeat

Batch Processing

Records are processed in batches for efficiency. Batch Size determines how many records are sent to Odoo in a single API request.

  • Batch Size 100 (default) - Good balance of speed and memory usage

  • Batch Size 50 - Use for large records or memory-constrained environments

  • Batch Size 200+ - Use for high-performance environments with good bandwidth

  • Batch Size 1 - Only for debugging (slowest, but processes one at a time)

Connection configuration

Before using the transform, you must define an Odoo database connection. The fields required are:

Field

Required

Description

Odoo connection name

Yes

A descriptive name for the connection in Hop.

Base URL (domain)

Yes

Full URL of the Odoo instance, e.g., https://mycompany.odoo.com.

Username

Yes

Odoo username for authentication (or API user).

Password

Yes

Odoo password or API key, depending on authentication method.

Database

Yes

Name of the Odoo database to query.


Practical examples

Example 1: HubSpot Contacts to Odoo (res.partner)

Scenario: Sync HubSpot contacts to Odoo, updating existing ones by email.

  1. Core Configuration:

  • Odoo Model: res.partner (Contacts)

  • Batch Size: 100

  • Return result info: Checked

  1. Lookup Keys:

  • Stream Field: email | Comparator: = | Odoo Field: email

  1. Field Mappings:

  • firstname + lastname → name

  • email → email

  • phone → phone

  • company → parent_id (or skip)

  • address → street

  • city → city

  • zip → zip

Example 2: Shopify Products to Odoo (product.product)

Scenario: Sync Shopify products to Odoo, matching by external ID.

  1. Lookup Keys:

  • Stream Field: shopify_id | Comparator: = | Odoo Field: external_id

  1. Field Mappings:

  • product_name → name (Required)

  • sku → default_code

  • price → list_price

  • description → description

  • shopify_id → external_id

Example 3: Multiple Lookup Keys (Email + Company)

Scenario: Match contacts by email AND company to handle name changes.

  1. Lookup Keys (AND logic):

  • Key 1: email = email

  • Key 2: company_name = parent_id.name

Result: Only updates if BOTH email AND company match existing record.