Understanding the JSON Salesforce Objects Section

In the JSON of a Salesforce source, you can access the Objects section (see Show Only One Configuration Section). This section presents all the Salesforce objects and fields to be indexed. It is one of the main sections affected, along with the Mappings section, when you customize the Salesforce source from the Coveo Cloud administration console (see Customizing the Salesforce Source Configuration in Cloud V2).

However, you might want to customize your source configuration further than what the Edit panel allows. Most of the time, this is done to index fields from parent or child objects without indexing the parent or child item. It can also be used to introduce polymorphic or conditional indexing, so that the indexed fields or items are dependent on certain fields.

This topic explains the structure of the JSON Salesforce source Objects section, so you can edit it better.

Basic Structure

The Objects section presents all the elements from the ObjectsToGet section. The most important part is the Query element, as it lists all the objects and fields to be returned when indexing the objects.

The following template is an example of the Objects section:

{
    "sensitive": false,
    "extendedData": {
        "Query": [
            {
                "ObjectName": "NameOfYourObject1",
                "Fields": {
                    "string": [
                        "FieldToIndex1",
                        "FieldToIndex2",
                        "FieldToIndexN"
                    ]
                }
            },
            {
                "ObjectName": "NameOfYourObject2",
                "Fields": {
                    "string": [
                        "FieldToIndex1",
                        "FieldToIndex2",
                        "FieldToIndexN"
                    ]
                }
            }
        ]
    }
}

In this template, you must replace the following values with your desired ones:

  • NameOfYourObject 1 and 2 by the name of an object you want to index.

  • FieldToIndex 1 through N by all the object fields you want to index.

When manually adding Objects and Fields to index in the JSON, you must remember to add field mappings to your objects (see Edit the Mappings of a Source: [SourceName]).

Introducing Parent Relationships

Parent relationships allow you to index fields from a parent object without having to index the object itself.

The following template is an example of a parent relationship:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        }
    },
    "ParentRelationships": {
        "ParentRelationship": [
            {
                "RelationshipName": "ParentObject",
                "Fields": {
                    "string": [
                        "ParentObjectFieldToIndex1",
                        "ParentObjectFieldToIndex2",
                        "ParentObjectFieldToIndexN"
                    ]
                }
            }
        ]
    }
]

In this template, you must replace the following values with your desired ones:

  • NameOfYourObject by the name of an object you want to index.

  • FieldToIndex by the object fields you want to index.

  • ParentObject by the parent object from which you want to index fields.

  • ParentObjectFieldToIndex 1 through N by all the parent object fields you want to index.

You want to index your cases, but not your accounts. However, you still want to have the account name in the case fields.

In the JSON, in the Query element, you enter the following:

"Query": [
    {
        "ObjectName": "Case",
        "Fields": {
            "string": [
                "CaseNumber",
                "Description",
                "Subject"
            ]
        }
    },
    "ParentRelationships": {
        "ParentRelationship": [
            {
                "RelationshipName": "Account",
                "Fields": {
                    "string": [
                        "Name"
                    ]
                }
            }
        ]
    }
]

Remember to add a %[Account.Name] mapping to your object (see Edit the Mappings of a Source: [SourceName]).

Inside the query of your parent relationship, you can add parent relationships, polymorphic relationships, or conditional indexing (see Add Conditional Indexing for a Salesforce Source).

You need to add it after the Fields declaration, as such:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        }
    },
    "ParentRelationships": {
        "ParentRelationship": [
            {
                "ObjectName": "NameOfYourObject",
                "Fields": {
                    "string": [
                        "FieldToIndex"
                    ]
                },
                "ParentRelationships": ...
            }
        ]
    }
]

Introducing Child Relationships

Child relationships, like parent relationships, allow you to index fields from a child object without indexing the child itself.

The following template is an example of a child relationship:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        },
        "ChildRelationships": {
            "ChildRelationship": [
                {
                    "RelationshipName": "ChildObject",
                    "Fields": {
                        "string": [
                            "ChildFieldToIndex1",
                            "ChildFieldToIndex2",
                            "ChildFieldToIndexN"
                        ]
                    }
                }
            }
        ]
    }
]

In this template, you must replace the following values with your desired ones:

  • NameOfYourObject by the name of an object you wish to index.

  • FieldToIndex by the object fields you wish to index.

  • ChildObject by the child object from which you want to index fields.

  • ChildFieldToIndex1 through N by all the child object fields you want to index.

You want to index your cases, but not your case comments. You however want the body of the case comment indexed as a field part of your cases.

In the JSON, in the Query element, you enter the following:

"Query": [
    {
        "ObjectName": "Case",
        "Fields": {
            "string": [
                 "CaseNumber",
                 "Description",
                 "Subject"
            ]
        },
        "ChildRelationships": {
            "ChildRelationship": [
                {
                    "RelationshipName": "CaseComments",
                    "Fields": {
                        "string": [
                            "CommentBody"
                        ]
                    }
                }
            ]
        }
    }
]

Remember to add a %[casecomments.commentbody] mapping to your object (see Edit the Mappings of a Source: [SourceName]).

Inside the query of your child relationship, you can add parent relationships, polymorphic relationships, or conditional indexing (see Add Conditional Indexing for a Salesforce Source).

You need to add it after the Fields declaration, as such:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        }
    },
    "ChildRelationships": {
        "ChildRelationship": [
            {
                "ObjectName": "CaseComments",
                "Fields": {
                    "string": [
                        "CommentBody"
                    ]
                },
                "ParentRelationships": ...
            }
        ]
    }
]

Creating Records from Children Fields

The CreateRecord option allows you to create an item from the children fields you index. As a Boolean option, it can either be set to true or false. Its default value is false.

The following template is an example of how to use the CreateRecord option:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        },
        "ChildRelationships": {
            "ChildRelationship": [
                {
                    "RelationshipName": "ChildObject",
                    "Fields": {
                        "string": [
                            "ChildFieldToIndex1",
                            "ChildFieldToIndex2",
                            "ChildFieldToIndexN"
                        ]
                    },
                    "CreateRecord": true
                }
            }
        ]
    }
]

</div>

Introducing Polymorphic Relationships

Polymorphic relationships allow you to index different fields depending on which object is returned (see Understanding Polymorphic Keys and Relationships).

The following template is an example of a polymorphic relationship:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        },
        "PolymorphicRelationships": {
            "PolymorphicRelationship": [
                {
                    "RelationshipName": "FieldToCheck",
                    "ObjectName": "ConditionObject",
                    "Fields": {
                        "string": [
                            "ConditionObjectFieldtoIndex1",
                            "ConditionObjectFieldtoIndex2",
                            "ConditionObjectFieldtoIndexN"
                        ]
                    }
                },
                {
                    "RelationshipName": "FieldToCheck",
                    "ObjectName": "ConditionObject",
                    "Fields": {
                        "string": [
                            "ConditionObjectFieldtoIndex1",
                            "ConditionObjectFieldtoIndex2",
                            "ConditionObjectFieldtoIndexN"
                        ]
                    }
                }
            ]
        }
    }
]

In this template, you must replace the following values with your desired ones:

  • NameOfYourObject by he name of an object you wish to index.

  • FieldToIndex by the object fields you wish to index.

  • FieldToCheck by the field whose object needs to be checked.

  • ConditionObject by the object which FieldToIndex field should be part of.

  • ConditionObjectFieldtoIndex1 through N by all the fields you want to index from the condition object.

When indexing your events, you want to index different fields depending on whether the what field is an Account or an Opportunity.

When the Event is related to an Account, you want to index its NumberOfEmployees field, and when the event is an Opportunity, you want to index its Amount field.

In the JSON, in the Query element, you enter the following:

"Query": [
    {
        "ObjectName": "Event",
        "Fields": {
            "string": [
                "Subject"
            ]
        },
        "PolymorphicRelationships": {
            "PolymorphicRelationship": [
                {
                    "RelationshipName": "What",
                    "ObjectName": "Account",
                    "Fields": {
                        "string": [
                            "NumberOfEmployees"
                        ]
                    }
                },
                {
                    "RelationshipName": "What",
                    "ObjectName": "Opportunity",
                    "Fields": {
                        "string": [
                            "Amount"
                        ]
                    }
                }
            ]
        }
    }
]

Remember to add a %[what_account.numberofemployees] and a %[what_opportunity.amount] mapping to your object (see Edit the Mappings of a Source: [SourceName]).

You can add parent or child relationships in your polymorphic relationships, by using the following syntax:

"Query": [
    {
        "ObjectName": "NameOfYourObject",
        "Fields": {
            "string": [
                "FieldToIndex"
            ]
        },
        "PolymorphicRelationships": {
            "PolymorphicRelationship": [
                {
                    "RelationshipName": "FieldToCheck",
                    "ObjectName": "ConditionObject",
                    "Fields": {
                        "string": [
                            "ConditionObjectFieldtoIndex1",
                            "ConditionObjectFieldtoIndex2",
                            "ConditionObjectFieldtoIndexN"
                        ]
                    },
                    "ParentRelationships": {
                        "ParentRelationship": [
                            {
                                "RelationshipName": "ParentObject",
                                "Fields": {
                                    "string": [
                                        "ParentObjectFieldToIndex"
                                    ]
                                }
                            }
                        ]
                    }
                },
                {
                    "RelationshipName": "FieldToCheck",
                    "ObjectName": "ConditionObject",
                    "Fields": {
                        "string": [
                            "ConditionObjectFieldtoIndex1",
                            "ConditionObjectFieldtoIndex2",
                            "ConditionObjectFieldtoIndexN"
                        ]
                    }
                }
            ]
        }
    }
]

Introducing Conditional Indexing

You can add conditional indexing directly from the Salesforce source configuration (see Manage Conditions Applied to an Object: [ObjectName] - Panel).

To prevent potential issues and source configuration errors, you are encourage to use the source configuration instead of editing the JSON.

The Salesforce source allows you to index items only when they meet specific conditions, which can reduce the size of your index.

To do so, you must enter the condition in the source JSON in the ObjectsToGet element. It must be included as part of the object you wish to index conditionally, after its field declaration.

For former Coveo Cloud V1 users, the Coveo Cloud V2 conditional indexing is the equivalent to the Manage Exclusion option from Coveo Cloud V1 (see Customizing the Salesforce Source Configuration).

There are two ways to add conditional indexing for a Salesforce source:

  • QueryCondition: Allows you to change the operator used in the created SOQL query.

  • InConditionValue: Allows you to list the allowed values in the created SOQL query.

QueryCondition

The QueryCondition element allows you to index items that answer to a specific query.

The conditions must respect the following template:

"Query": [
    {
        "ObjectName": "Object",
        "Fields": {
            "string": [
                "ObjectField"
            ]
        },
        "Conditions": {
            "queryConditionOrQueryCondition2OrInCondition": [
                {
                    "QueryCondition": {
                        "Field": "FieldToCheck",
                        "Operator": "OperatorToUse",
                        "Value": "ValueToMatch"
                    }
                }
            ]
        }
    }
]

In this template, you must replace the following values with your desired ones:

  • Object and ObjectField: The Salesforce object and its fields to index (see Understanding the JSON Salesforce Objects Section).

  • FieldToCheck: The Salesforce field the source should check for the matching value. The field must be one of the fields specified in your object, or the source will fail to build.

  • OperatorToUse: The operator you want to use when comparing your field to its value. The accepted values are =, !=, >, <, <=, >=, Like, NotLike, Includes, and Excludes (see SOQL Operators).

  • ValueToMatch: The value the field must have to be indexed.

    String values must be between double and single quotes (e.g., "'Phone'").

    Boolean and Date values must be in double quotes (e.g., "true", "2017-06-01T00:00:00.0000000-00:00").

It results in the following query:

SELECT ObjectField FROM Object WHERE FieldToCheck OperatorToUse ValueToMatch

You can decide to add several QueryCondition one after the other, inside the queryConditionOrQueryCondition2OrInCondition element. The resulting SOQL query simply adds AND to every condition.

For your Salesforce source, you wish to index Cases only when their Origin field is not Phone.

In the JSON of the source, as part of the ObjectsToGet element, you have the following elements:

"Query": [
    {
        "ObjectName": "Case",
        "Fields": {
            "string": [
                "Origin"
            ]
        },
        "Conditions": {
            "queryConditionOrQueryCondition2OrInCondition": [
                {
                    "QueryCondition": {
                        "Field": "Origin",
                        "Operator": "!=",
                        "Value": "'Phone'"
                    }
                }
            ]
        }
    }
]

This results in the following query:

SELECT Origin FROM Case WHERE Origin != 'Phone'

InCondition

The InCondition element allows you to index items only when one of their field has a specific value from your listed values.

The condition must respect the following template:

"Query": [
    {
        "ObjectName": "Object",
        "Fields": {
            "string": [
                "ObjectField"
            ]
        },
        "Conditions": {
            "queryConditionOrQueryCondition2OrInCondition": [
                {
                    "InCondition": {
                        "Field": "FieldToCheck",
                        "InConditionValue": {
                            "name": "AllowedValues",
                            "declaredType": "com.coveo.cloud.source.model.sourceconfig.salesforce.generator.AllowedValues",
                            "scope": "javax.xml.bind.JAXBElement$GlobalScope",
                            "value": {
                                "ConditionValue": [
                                    {
                                        "name": "FieldType",
                                        "declaredType": "java.lang.String",
                                        "scope": "javax.xml.bind.JAXBElement$GlobalScope",
                                        "value": "ValueToMatch",
                                        "nil": false
                                    }
                                ]
                            },
                            "nil": false
                        }
                    }
                }
            ]
        }
    }
]

In this template, you must replace the following values with your desired ones:

  • Object and ObjectField: The Salesforce object and its fields to index (see Understanding the JSON Salesforce Objects Section).

  • FieldToCheck: The Salesforce field the source should check for the matching value. The field must be one of the fields specified in your object, or the source will fail to build.

  • FieldType: The type of the field to check. The accepted values are:

    • SoqlString: a string.

    • SoqlBoolean: a Boolean value.

    • SoqlDateTime: a date. The format must respect the SOQL date format (see Date Formats and Date Literals).

  • ValueToMatch: The value the field must have to be indexed. Ensure the value is still in quotes, even for Boolean values.

It results in the following query:

SELECT ObjectField FROM Object WHERE FieldType IN ('ValueToMatch')

For your Salesforce source, you want to index Cases only when their Status field is either Escalated or Closed.

In the JSON of the source, as part of the ObjectsToGet element, you have the following elements:

"Query": [
    {
        "ObjectName": "Case",
        "Fields": {
            "string": [
                "Status"
            ]
        },
        "Conditions": {
            "queryConditionOrQueryCondition2OrInCondition": [
                {
                    "InCondition": {
                        "Field": "Status",
                        "InConditionValue": {
                            "name": "AllowedValues",
                            "declaredType": "com.coveo.cloud.source.model.sourceconfig.salesforce.generator.AllowedValues",
                            "scope": "javax.xml.bind.JAXBElement$GlobalScope",
                            "value": {
                                "ConditionValue": [
                                    {
                                        "name": "SoqlString",
                                        "declaredType": "java.lang.String",
                                        "scope": "javax.xml.bind.JAXBElement$GlobalScope",
                                        "value": "Escalated",
                                        "nil": false
                                    },
                                    {
                                        "name": "SoqlString",
                                        "declaredType": "java.lang.String",
                                        "scope": "javax.xml.bind.JAXBElement$GlobalScope",
                                        "value": "Closed",
                                        "nil": false
                                    }
                                ]
                            },
                            "nil": false
                        }
                    }
                }
            ]
        }
    }
]

This results in the following query:

SELECT Status FROM Case WHERE Status IN ('Escalated', 'Closed')