Updating Products by Search
This guide shows you how to update every product that matches a search in one request. Use it when you know which products to change but not their ids, for example to mark all products from one vendor as on sale, or to add a field to every variant of a parent product.
Update Products patches a known list of documents by _id. This endpoint instead takes one or more searches, runs each one, and applies the fields in value to every document the search returns.
Prerequisites
- A Marqo Cloud account (sign up here)
- Your Marqo API key (find your API key guide)
- An existing ecommerce index with products (add products guide)
Update Documents by Search
Endpoint: PATCH https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/documents-search
Authentication: Authorization: Bearer {api_key}
Request Body:
{
"searches": [
{
"search": { "filter": "vendor:(Acme Apparel)" },
"value": { "on_sale": true }
}
]
}
| Parameter | Type | Default | Description |
|---|---|---|---|
searches | Array | (required) | One or more search and value pairs. Must contain at least one entry. Each entry is processed independently. |
searches[].search | Object | {} | A search request body that selects the documents to update. It accepts the same fields as Search, such as q and filter. When omitted or empty, it matches every document in the index. |
searches[].value | Object | (required) | The fields to set on every matching document. Works like the body of a partial update: only the fields you include change, other fields are left as they are. |
Only these keys are accepted. A request with an unknown key at the top level or inside an entry returns 422.
Restrictions on value
The request is rejected with 422 when any value:
- is empty.
valuemust contain at least one field to update. - contains
_id. The target documents are selected bysearch, not by id. - contains a reserved field.
_mq_version,_mq_last_write_job_id,_mq_promo_price_basis,_mq_discount_basisand_mq_price_factorare managed by Marqo and cannot be set.
Example: put a vendor's products on sale
The example below uses a custom vendor field and a custom on_sale field that were added when the products were indexed. Adjust the filter to the fields in your index.
- cURL
- JavaScript
curl -X PATCH https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/documents-search \
-H "Authorization: Bearer {api_key}" \
-H "Content-Type: application/json" \
-d '{
"searches": [
{
"search": { "filter": "vendor:(Acme Apparel)" },
"value": { "on_sale": true }
}
]
}'
fetch(
"https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/documents-search",
{
method: "PATCH",
headers: {
"Authorization": "Bearer {api_key}",
"Content-Type": "application/json",
},
body: JSON.stringify({
searches: [
{
search: { filter: "vendor:(Acme Apparel)" },
value: { on_sale: true },
},
],
}),
}
);
Note: Replace {index_name} with your actual index name and {api_key} with your API key.
Several updates in one request
Each entry in searches carries its own search and its own value, so one request can apply different updates to different sets of products:
{
"searches": [
{
"search": { "filter": "vendor:(Acme Apparel)" },
"value": { "on_sale": true }
},
{
"search": { "filter": "parentProductId:(8834011234567)" },
"value": { "shipping_class": "oversized" }
}
]
}
Response
The update is queued and runs asynchronously. A successful request returns 202 Accepted with the id of the job that performs it:
{
"jobId": "9c1f6a2e-3b4d-4e5f-8a9b-0c1d2e3f4a5b"
}
Use the Monitor Jobs endpoints to follow progress. Because the number of matching documents is not known until each search runs, the job counts one search as one unit of work: the job's item counts (totalItems, processedItems, failedItems) refer to entries in searches, not to individual documents.
Response Status Codes
| Status Code | Description |
|---|---|
202 | The update was queued. The body contains jobId. |
401 | Missing or invalid API key. |
404 | The index name is unknown, belongs to another account, or is not ready to serve requests yet. Body: {"error": "Marqo settings not found for shop {system_account_id}-{index_name}"}. |
422 | searches is empty, a value is empty, a value sets _id or a reserved _mq_* field, or the body contains an unknown key. |
500 | Internal error. |
An update is skipped when a newer version of a matched document has already been indexed, which is
reported as the CONFLICT job status. Send the x-marqo-bypass-conflict: true header to force the
write through. See bypassing the version conflict check.
Best Practices
- Check the search first. Run the same
searchbody against the Search endpoint and confirm it returns the products you expect before sending the update. A search with nofilterand noqupdates every document in the index. - Prefer filters to queries. A
filterselects documents by exact field values, so the set of updated documents is predictable. A textqranks by relevance and is better suited to retrieval than to choosing which documents to modify. - Keep updates idempotent. Set fields to the values they should have rather than relying on the previous value, so re-running the request after a failure is safe.