Use this feature to UPSERT or DELETE in your datamart.
How-to
Use the endpoints to create a with theUSER_PROFILEdocument type and APPLICATION_X_NDJSON mime type. Only ndjson data is supported for user profiles.
You can, of course, upload multiple user profiles at once. Note the uploaded data is in ndjson and not json. That means the different profiles are not separated by commas, but by a line separator \n
Then, create anwith your user profile import commands formatted in ndjson .
User profile import command
Each line in the uploaded file can have the following properties:
field
type
description
operation
Enum
Either UPSERT or DELETE
compartment_id
String (Optional)
user_account_id
String (Optional)
email_hash
String (Optional)
user_agent_id
String (Optional)
update_strategy
Enum (Optional)
Only considered when operation == UPSERT
Values are PARTIAL_UPDATE, PARTIAL_DELETE, FORCE_REPLACE
user_profile
JSON Object (Optional)
Mandatory when operation == UPSERT.
When importing profiles with identifiers, only one identifier is allowed per line. For example, you shouldn't specify the user agent ID if the Email Hash is already used in a line.
Example
First create the document import using the call below. You can also reuse a document import that was previously created
Each user profile import you do will be a new execution of the document import created. Here is an example :
# Here we use the combination of compartment_id and user_account_id acting as identifier
curl -X POST \
https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
-H 'Authorization: <API_TOKEN>' \
-H 'Content-Type: application/x-ndjson' \
-d '{
"operation": "UPSERT",
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"user_profile": {
this": "is",
"a":"test"
}
}'
Possible update strategies when updating existing user profiles
When doing an UPSERT if you want to update existing profiles in your datamart you should use the update_strategy field.
PARTIAL_UPDATE and PARTIAL_DELETE
If you wish to perform targeted updates on existing profiles without overwriting the whole existing user profile object, you should use the PARTIAL_UPDATE or PARTIAL_DELETE values of the update_strategy field.
You should mark a field with the directive @UpdateStrategyKey inside of each object you would like to make updates on. Inside of a given object, the field that has the directive will serve to identify the given object based on the value of this field in the update request.
This will allow you to alter data of inner objects or arrays of the user profile and in particular : add objects or update fields inside of objects or arrays. This is especially useful for intricated structures such as arrays of objects inside of objects, arrays of arrays of objects...
It is possible to define a hierarchy of inner objects while using @UpdateStrategyKey at each level
However, @UpdateStrategyKey should only be set to one property inside a given object
#This is allowed
type LoyaltyCard {
card_id:String @UpdateStrategyKey
benefits: Int
last_visit_date: String
other_information : [OtherInformation]
}
type OtherInformation {
info_id: String @UpdateStrategyKey
}
################################
#This is not allowed
type LoyaltyCard {
card_id:String @UpdateStrategyKey
benefits: Int @UpdateStrategyKey
last_visit_date: Date
}
Example
Let's consider this simplified schema on which you would like to update values of the LoyaltyCard object without overwriting the whole profile.
## Schema extract
type UserProfile {
loyalty:Loyalty
}
type Loyalty {
cards:[LoyaltyCard] #it's an array of objects
}
type LoyaltyCard {
card_id:String @UpdateStrategyKey # we add the directive to be able to update LoyaltyCard by referecing card_id in the update request
benefits: Int
last_visit_date: String
}
And this import execution using the PARTIAL_UPDATE for instance
# Partial update of the benefits of a given card
curl -X POST \
https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
-H 'Authorization: <API_TOKEN>' \
-H 'Content-Type: application/x-ndjson' \
-d '{
"operation": "UPSERT",
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"update_strategy": "PARTIAL_UPDATE",
"user_profile": {
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc", #value of the field marked with @UpdateStrategyKey of the object to update
"benefits": 500 #we want to update the benefits value of the card with "card_id":"abc"
}
]
}
}
}'
#2 - Update an inner object property - PARTIAL_UPDATE
// Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ //request changing the benefits value of the existing card
{
"card_id": "abc", // value of the field marked with @UpdateStrategyKey of the inner object to update
"benefits": 100
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ //
{
"card_id": "abc",
"benefits": 100, // value has been updated
"last_visit_date": "2024-01-01"
}
]
}
}
Remark : arrays of scalar values are treated as scalars. See example below :
// Extract of existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"my_array_of_scalars": [1,2,3],
...
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"my_array_of_scalars": [4,5,6],
...
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"my_array_of_scalars": [4,5,6], // the value of the property has been replaced by the new value
...
}
#3 - Delete an inner object property - PARTIAL_UPDATE
For a non mandatory value you can also set a given field to null (but not an object directly). For instance in the previous example you could have done the following :
// Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": null // set the value to null
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ // benefits value has been cleared
{
"card_id": "abc",
"last_visit_date": "2024-01-01"
}
]
}
}
#4 - Update inner object and add new object - PARTIAL_UPDATE
//Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 100,
"last_visit_date": "2024-01-01"
},
{
"card_id": "def",
"benefits": 600,
"last_visit_date": "2025-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_DELETE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc" // value of the field marked with @UpdateStrategyKey of the inner object to delete
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ // the card with card_id = "abc" has been deleted
{
"card_id": "def",
"benefits": 600,
"last_visit_date": "2025-01-01"
}
]
}
}
If you wish to delete a specific property value inside an object, you should use PARTIAL_UPDATE. Please refer to use case #3.
Constraints and limitations
Schema related constraints :
The update request must respect the datamart schema :
If a property is in the payload of the request but not declared in the schema, the whole request will fail. However, if a property is already present in the profile but not declared in the schema, it will not be overwritten by a partial update or delete. In fact it will not be possible to update such property unless using FORCE_REPLACE
If the types of the properties in the payload of the request do not respect the schema, the whole request will fail.
Limitations :
If a property in the schema has a directive such as @Property(path: “[parent].property”) (referencing [parent] in path) : this property cannot be updated with the partial update
Updatable properties cannot be computed values such as : computed field, ML function, results of function.
FORCE_REPLACE
When importing user profiles using UPSERT, if you wish to update existing profiles by completely overwriting the existing profiles you should use the FORCE_REPLACE value of the update_strategy field : the user profile will be completely replaced by the object passed in the user_profile field.
Mandatory when the operation is UPSERT.
If true, then the User Profile will be completely replaced by the object passed in the user_profile field.
If false, the object passed in the user_profile field will be merged with the existing User Profile of the User Point.
merge_objects
Boolean (Optional)
Only considered if force_replace is false.
Manage the comportement between two objects with a same property.
If false (default value), the new object overrides the existing one.
The Compartment ID, acting as a user in correlation with user_account_id
The User Account ID, acting as an in correlation with compartment_id
The Email Hash, acting as an
The User Agent ID, acting as an
JSON Object representing the User Profile. Please refer to the for more information.
These options work together with a @UpdateStrategyKey that should be defined on the schema of the datamart you are working on. You should first in order to include this new directive.
If true the new object is merged in deep to the existing one (see ).