Salesforce Connector Guide
Notice
The content in this document represents the current view of Coveo as of the date of publication. Because Coveo continually responds to changing market conditions, information in this document is subject to change without notice. For the latest documentation, visit our website atwww.coveo.com.
Copyright © 2014, Coveo Solutions Inc.
All rights reserved.
Coveo is a trademark of Coveo Solutions Inc. This document is protected by copyright and other intellectual property law and is subject to the confidentiality and other restrictions specified in the Coveo License Agreement.
Document part number: PM-131004-EN Publication date: 12/19/2015
Table of Contents
1. Salesforce Connector 1
1.1 Advantages Relative to the Legacy Connector 1
1.2 Features 1
2. Salesforce Connector Deployment Overview 7
3. Salesforce Connector Requirements 9
4. Creating a Salesforce User Identity 10
4.1 Creating a Dedicated Salesforce Crawling Account 11
4.2 Getting the Security Token for Your Salesforce Account 13
5. Getting Salesforce Client_ID and Client_Secret Values 14
6. Salesforce ObjectsToGet Configuration File 19
6.1 Salesforce Object Definition 19
6.2 Configuration File Elements 20
6.3 XML Schema Definition 30
6.4 Creating a Salesforce ObjectsToGet Configuration File 32
6.5 Salesforce ObjectsToGet Configuration File Example for Standard Objects 33 6.6 Salesforce ObjectsToGet Configuration File Example for Knowledge Base 45 6.7 Salesforce ObjectsToGet Configuration File Example for CRM Content 48 6.8 Salesforce ObjectsToGet Configuration File Example for Chatter Objects 51
6.9 Salesforce Connector Configuration Recipes 54
6.9.1 Indexing all Knowledge Base Versions and States 54
6.9.2 Excluding Archived Knowledge Base Articles 56
6.9.3 Indexing Knowledge Base Attachments 57
6.9.4 Fetching Records With Parent Relationships That Must Be Incrementally Updated 57
6.9.5 Fetching Child Relationship to Use for Folding 59
6.9.6 Fetch Child Relationship to Use to Increase or Reduce Results From Queries 60
6.9.7 Minimizing API Calls and Object Description Prefetching 60
6.9.8 Fetching Records Faster Using the Turbo Mode Runner 61
6.9.9 Reducing the Metadata Package Size by Scoping Parents of ContentVersion and Attachment
Objects 62
6.9.10 Choosing the Optimal Record Modification Date Field 63
6.9.11 Removing Leading Zeroes of a Field 63
6.9.12 Using the Currency Field Converter 63
6.9.13 Using the FiscalYearResolver 64
6.9.14 Fixing the Feed Tracking Error 64
6.9.15 Indexing More Than the Built-in FeedItem Types 64
7. Creating a Salesforce Mapping File 65
7.1 Salesforce Mapping File Example for Standard Objects 66
7.2 Salesforce Mapping File Example for Knowledge Base 76
7.3 Salesforce Mapping File Example for CRM Content 78
7.4 Salesforce Mapping File Example for Chatter Objects 80
8. Configuring a Salesforce Security Provider 82
8.1 Configuring an Email Security Provider 84
8.2 Configuring an Active Directory Security Provider 86
9. Configuring and Indexing a Salesforce Source 89
9.1 Modifying Hidden Salesforce Source Parameters 95
9.2 Adding an Explicit Connector Parameter 97
10. Troubleshooting Salesforce Connector Issues 101
10.1 API Security Token Required 101
10.2 Expired Access/Refresh Token 101
10.3 Missing ionic.zip File 101
11. Refreshing Security Caches 102
1. Salesforce Connector
CES 7.0.5785+ (August 2013)
The on-premises Salesforce connector is part of the Coveo for Salesforce license and is therefore available only with Coveo for Salesforce (seeCoveo for Salesforce).
The Coveo Salesforce connector allows you to crawl Salesforce content and bring it into the unified index, making it easily searchable by end-users.
1.1 Advantages Relative to the Legacy Connector
This second generation Salesforce connector offers the following advantages over the Salesforce Legacy connector:
l Indexing of Salesforce permissions rather than applying the same permission on all source items (see
"Indexed Salesforce Security" on page 1)
l Improved performance and reduced API calls
l Indexing of Knowledge Base articles and CRM content files
l Takes advantage of recent Salesforce API versions
1.2 Features
Indexed Salesforce Content
The connector can index the following Salesforce content:
l Service Cloud standard/custom objects and fields
l Multilingual Knowledge base articles
l Chatter feed items and files[more]
l CRM Content (binary files such as PDF)
l Sharing permissions
l Sandbox and production environments
l Inactive users
l User visibility Indexed Salesforce Security
The connector can index the permissions of each Salesforce item allowing the index to only return Salesforce search results that the user performing the query has the permissions to see.
The Coveo index replicates the Salesforce security model for:
l View All permissions
The Salesforce connector fully supports all View All permissions given through a user profile, more explicitly View All Data which applies to every object, View All User which allows a view all on the user object, and View All on specific objects such Accounts, Cases, Leads, and Contact.
Note: As Salesforce does not support View All Data onContentVersion, the permission is replicated in the connector.
l Sharing permissions
An administrator can secure private objects with the owner, collaboration group, group, user, bosses of a given user, subordinates of a given user, or Community (also called Network) sharing permission types.
l Profile associated to the user
The profile specifies standard and custom object permissions for users associated to this profile.
Note: Any user which is granted Read access for an object by his profile is entitled to search for records of the given type.
l Organization-wide defaults sharing settings
These settings specify the level of access your users have to each other's data.
l Shared content
A user can share private content with specific users or groups.
Note: File sharing settings applied to Chatter files and CRM Content documents are also supported. File sharing settings are not the same as the sharing settings for private objects.
l CRM Content
CRM Content users have access to CRM Content Documents when they are entitled to read such documents in the library to which the documents belong.
l Chatter
Chatter posts and comments inherit the permissions of the record onto which they are posted, no matter if that record is public, private, a group or a user.
Note: Public and privateCollaborationGroupsare supported.
l Communities
Sharing sets are supported in Communities.
l Role hierarchy within the organization
With a role hierarchy, private documents are visible by the owner, but also by all parents of the owner in the hierarchy.
Permission sets given to individual users can extend (not restrict) their permissions beyond what is specified in their profile.
l License type
A user license entitles a user to different functionality within Salesforce and determines which profiles and permission sets are available to the user, so the Coveo index indirectly replicates user license type permissions by indexing permissions from profiles and permission sets.
Note: The connector does not support the following security aspects:
l Apex managed sharing
l IP based permissions
The Coveo connector cannot index restrictions on login IP addresses or hours configured in Salesforce.
The consequence is that your Salesforce users can access Coveo search interfaces and review Salesforce content from any IP address at any time.
l Field level security (FLS)
For Enterprise, Unlimited, and Developer Salesforce editions, visibility of individual fields can be granted or denied to users or groups to fine-tune the access control in a permission set or a profile. The Coveo connector cannot index these permissions. The consequence is that a user that is denied access to a field could see the content of this field in Coveo search results. Note however that this is also the case for Salesforce search results (see the Salesforce documentField-Level Security Overview).
l Permission changes replicated with re-indexing, not with incremental refreshes
When permissions change in Salesforce for a profile, permission set, object sharing, or object security level (Public versus Private), the changes are not replicated in the index on the next incremental refresh.
You must refresh the source to capture permission changes.
l Shared personal groups
A user can share content with a personal group. These sharing permissions cannot be indexed because they are currently not reported by the Salesforce API. The consequence is that members of the personal group will not see the shared content in Coveo Organization results. This limitation is therefore not a security hole.
l Frozen users are not supported
The user that are frozen using the Freeze button are not denied access to the search (seeFreezing User Accounts).
l Knowledge Base (KB) item permissions:
In Salesforce, you can map User Roles to KB data categories (e.g.: members of theTechnical Agent role can only see KB articles under theTechnicaldata category). This mapping information is not available from the Salesforce API and therefore cannot be indexed. Consequently, in search results, all users can see all KB articles under all data categories.
l When the organization-wide default is set to Controlled by Parent, a maximum master-detail relationship depth of two levels is supported (seeSharing Default Access Settings).
Example: When you index a subdetail object, the detail parents are correctly determined but the master parents are considered public because there are three levels (master-detail-subdetail).
Incremental Refresh
automatically.
Notes:
l The incremental refresh feature limitations:
o Does not work when the last incremental refresh was performed more than 30 days ago. This will trigger a full refresh of the content.
o Not supported for all not replicateable deleted objects such as deleted ContentVersion (CRM Content and Chatter files) attachments and other items.
o CES 7.0.7914– (October 2015)A source full refresh or rebuild is needed to capture the deletion of knowledge base articles and the attachment (or the contrary) of articles on a case.
l CES 7.0.8047+ (December 2015)After you upgrade CES, it is recommended to perform a full refresh of your source(s) containing KB articles to take account of possible URI changes. You will also possibly have to change the ObjectsToGet configuration file depending on your needs (seeSalesforce Connector Configuration Recipes). Theses modifications allow the connector to fully support the incremental refresh as well as the publish status changes of KB articles using stable URIs now produced by default.
l CES 7.0.7914– (October 2015)Stable URIs can only be produced with the help ofCoveo Supportfor the latest version of online articles when draft and archived articles are not indexed.
Customizable ObjectsToGet Configuration File
You can customize items that the Coveo crawler retrieves from Salesforce (see"Creating a Salesforce ObjectsToGet Configuration File" on page 32).
Customizable Mapping File
You can customize how the fields of Salesforce objects are mapped to searchable fields in the Coveo index (see"Creating a Salesforce Mapping File" on page 65).
Connector Feature History
Coveo Platform
version Date Features
7.0.8047 December
2015
Full support of incremental refreshes on knowledge articles and indexing their publish status
7.0.7183 November
2014
Support validating the ObjectsToGet with an XSD[more]
7.0.6767 June 2014 l Support incremental modification of knowledge base articles versions and states[more]
l Support incremental modification of user profiles
Coveo Platform
version Date Features
7.0.6424 February
2014
Knowledge content searchable by article number without inputting leading zeroes
7.0.6339 January
2014
l Partial incremental refresh support on knowledge articles
l Support multilingual knowledge articles
7.0.6196 November
2013
Adding support to crawl Chatter feed items and files.
7.0.5785 August 2013 Introduction of this second generation Salesforce connector
What's Next?
Review the deployment process for the Salesforce connector (see"Salesforce Connector Deployment Overview"
on page 7).
2. Salesforce Connector Deployment Overview
The following procedure outlines the steps needed to index a Salesforce source. The steps indicate the order in which you must perform configurations tasks. When needed, the steps refer to a detailed procedure.
The Salesforce connector can index various Salesforce content types:
l Service Cloud standard and custom objects and fields
l Knowledge base articles
l Chatter
l CRM Content
When you want to index more than one of these Salesforce content types, you must use the following procedure to create a configuration (ObjectsToGet configuration file, mapping file, and source) for each of them because they cannot share the same set of configuration parameters.
To deploy the Salesforce connector
1. Validate that your environment meets the requirements (see"Salesforce Connector Requirements" on page 9).
2. Configure the user identity
The Coveo connector needs an account to connect to your Salesforce organization and access the entire content that you want to index. You must create a CES user identity to hold the credentials of this Salesforce account (see"Creating a Salesforce User Identity" on page 10).
3. Get SalesforceClient_IDandClient_Secretvalues
The Coveo security provider and connector for Salesforce must know theClient_IDandClient_Secret values for your Salesforce organization to be authorized to access its content (see"Getting Salesforce Client_
ID and Client_Secret Values" on page 14).
4. Create an ObjectsToGet configuration file
An ObjectsToGet XML configuration file tells the crawler which Salesforce items to retrieve (see"Salesforce ObjectsToGet Configuration File" on page 19).
You must create your custom ObjectsToGet XML configuration file before configuring your source. You can create the file based on examples that include standard objects and include your custom objects (see
"Creating a Salesforce ObjectsToGet Configuration File" on page 32).
5. Configure a mapping file
A Salesforce source needs a mapping file to know how to map retrieved Salesforce items to CES index fields.
You must create a mapping file before you configure your Salesforce source (see "Creating a Salesforce Mapping File" on page 65).
6. Create a custom Salesforce field setCES 7.0.6607+ (April 2014)
a. The Salesforce source needs a field set matching the CES fields that are included in the mapping file. It is recommended to start by importing the default Salesforce field set file ([CES_Path]
\Bin\Coveo.CES.CustomCrawlers.Salesforce.FieldSet.xml) to create fields for all the metadata available by default from Salesforce content.
b. When you created custom Salesforce object and fields, add corresponding fields to the field set.
7. Configure an Email security provider
Note: For a Salesforce Knowledge Base source, you do not need to perform this procedure. Knowledge Base permissions cannot be indexed so no Email security provider is needed.
In Salesforce, users are identified by their email addresses. Consequently, permissions returned by the Salesforce security provider for each document are email addresses. The Salesforce security provider then requires another security provider to uniquely identify users from their email addresses.
The security provider type to use depends on how users are authenticated when they access the search interface:
l When authenticated with their email address, use an Email security provider (see"Configuring an Email Security Provider" on page 84).
l When authenticated with their Active Directory account, use an Active Directory security provider (see
"Configuring an Active Directory Security Provider" on page 86).
Note: An Active Directory security provider is appropriate only when the User Principal Name (UPN) matches the email address for all users.
Note: You may require to also use a Regex Transform Member Name security provider in between the two other security providers to map member types. ContactCoveo Supportfor assistance.
8. Configure a Salesforce security provider
Note: For a Salesforce Knowledge Base source, you do not need to perform this procedure. Knowledge Base permissions cannot be indexed so no Email security provider is needed.
A Salesforce source needs a Salesforce security provider (see "Configuring a Salesforce Security Provider" on page 82).
9. Configure and index the Salesforce source
The Coveo connector needs to know details about your Salesforce organization to be able to index the desired content (see"Configuring and Indexing a Salesforce Source" on page 89).
10. If you encounter issues:
l Solve typical issues that return error messages (see"Troubleshooting Salesforce Connector Issues" on page 101).
l Consider adding and modifying default values of hidden source parameters (see"Modifying Hidden Salesforce Source Parameters" on page 95).
3. Salesforce Connector Requirements
Your environment must meet the following requirements to be able to use the Coveo connector for Salesforce repositories:
l CES 7.0.5785+ (August 2013)
l Coveo for Salesforce license
The Salesforce connector is only available on-premises if you have acquired a suitable Coveo for Salesforce license (seeCoveo for Salesforce).
Note: You can see if the Salesforce connector is enabled in your CES 7.0 instance from the CES Administration Tool.
l An active Salesforce account to a Salesforce organization
The crawling account must have permissions to read all the types of content that you want to index (see
"Creating a Salesforce User Identity" on page 10).
What's Next?
Create a user identity to be used by the Coveo connector to crawl your Salesforce content (see"Creating a Salesforce User Identity" on page 10).
4. Creating a Salesforce User Identity
The Coveo connector and security provider for Salesforce must use a user account to connect to your Salesforce organization.
When an application such as the Coveo connector accesses your Salesforce content through the API, it must provide credentials where the Security Token associated to the account is appended to the password.
Important:Salesforce may regularly request a password change which will generate a new Security Token at the same time. You must then each time update the user identity with the new password and Security Token.
To create a Salesforce user identity
1. In the Salesforce organization that you want to index:
a. Select or create an account to be used by the Coveo connector and security provider to access your Salesforce content (see"Creating a Dedicated Salesforce Crawling Account" on page 11).
b. Find the Salesforce Security Token for this account (see"Getting the Security Token for Your Salesforce Account" on page 13).
2. On the Coveo server, access the Administration Tool.
3. In the Administration Tool, select Configuration > Security.
4. In the navigation panel on the left, select User Identities.
5. In the User Identities page, click Add.
6. In the Modify User Identity page:
a. In the Name box, enter a name for this user identity.
b. In the User box, enter the user name of the selected Salesforce account, typically the email address.
c. In the Password box, enter the password to which you append the Security Token for the selected Salesforce account with no space in between.
Example: When the password isThisIsMyPasswordand the Security Token is
DU5PJU3GtHbQaX0zxiWoCMq8Z, then enterThisIsMyPasswordDU5PJU3GtHbQaX0zxiWoCMq8Z. d. Click Apply Changes.
What's Next?
Your Salesforce source and security provider will need to know theClient_IDandClient_Secretvalues for your Salesforce organization (see"Getting Salesforce Client_ID and Client_Secret Values" on page 14).
4.1 Creating a Dedicated Salesforce Crawling Account
The Coveo connector can use a Salesforce administrator account to access and crawl your Salesforce content. It is however a better practice to create dedicated Salesforce user, profile, and permission set for the Coveo crawling, that specify minimal permissions and access.
Note: It is strongly recommended to have separate dedicated Salesforce crawling accounts for each Salesforce source and security provider. When the Coveo crawler accesses Salesforce with the same user credentials too many times, Salesforce returnsINVALID_QUERY_LOCATORerror messages, such as the following:
Error with ID 'SALESFORCE_INVALID_QUERY': invalid query locator (INVALID_QUERY_LOCATOR) - This error can occur if a user is used more than once for sources that run in
parallel. To avoid this error, make sure to use only one user per source or alternate the refresh schedule of your sources.
To create a dedicated Salesforce crawling account
1. Using an administrator account, log in to your Salesforce organization.
2. In the user menu, select Setup.
3. Create a Salesforce profile dedicated to the Coveo crawler:
a. In the Setup page, select Manage Users > Profiles.
b. In the Profiles page, click New Profile.
c. In the Clone Profile page:
i. In the Existing Profile box, select an existing profile such as Read Only to be used as a template for the new profile according to the permissions you want to grant to the crawler.
ii. In the Existing Profile box, enter a name such asCoveoIndexer. iii. Click Save.
d. In the page for your new profile, click Edit and in the Administrative Permissions section:
i. Ensure that the API Enabled option is selected.
ii. Optionally, select the API Only User option as an additional security measure.
iii. Select the Modify All Data option when any of the following situation applies:
l CES 7.0.6225– (December 2013)
l You want to index the Salesforce item permissions.
Note: If you do not enable Modify All Data, be aware that the crawler will only index content to which it has access, so set up read access to objects accordingly.
iv. Optionally, as an additional security measure, in the Login IP Ranges section, select or create a login IP range to restrict the accessibility for this profile.
4. Create a Salesforce user dedicated to the Coveo crawler:
a. In the Setup page, select Manage Users > Users.
b. In the All Users page, click New User.
c. In the New User page:
i. Fill the required fields.
ii. In the Profile box, select the profile you just created.
iii. Click Save.
4.2 Getting the Security Token for Your Salesforce Account
When you create a Salesforce account, Salesforce sends an email message [email protected] subject: salesforce.com security token confirmationto the email address associated with the account.
This email message contains the Security Token for the account and is the only place where you can find the Security Token value. When you change the account password, the security token is also regenerated (so the previous one expires) and a similar email is sent.
To get the security token for your Salesforce account
1. In the mailbox for the email address associated with the Salesforce account to be used by the Coveo connector, look for the latest email message received [email protected]
subject: salesforce.com security token confirmation.
2. If you cannot find the latest email with security token, reset the security token:
a. Log in to Salesforce using the Salesforce account to be used by the Coveo connector.
b. In the User Menu, select Setup.
c. In the menu on the left, under Personal Setup, expand My Personal Information, and then click Reset My Security Token.
d. Follow onscreen instructions.
A new email message will be sent.
3. Open the message, and then copy the Security Token value.
Example: In the following email example, the Security Token value is highlighted.
5. Getting Salesforce Client_ID and Client_Secret Values
The Force.com platform implements the OAuth 2.0 Authorization Framework, so users can authorize applications to access Force.com resources.
When you configure the Coveo Salesforce security provider and Salesforce source, you must know theClient_ID andClient_Secrettoken values for the Salesforce organization that you want to index.
To get the Salesforce Client_ID and Client_Secret values
1. Using and administrator account, log into the Salesforce organization that you want to index.
2. On the User Menu, select Setup.
3. In the navigation menu on the left, under App Setup, expand Create, and then click Apps.
4. In the Apps page, in the Connected Application section, click New to create a new application that will use OAuth2 to gain access to the organization.
5. In the New Connected App page:
a. In the Basic Information section:
i. Enter meaningful names in the Connected App Name and API Name boxes.
ii. Enter your email in the Contact Email box so that you can receive messages from this application.
b. In the API (Enable OAuth Settings) section:
i. Select the Enable OAuth Settings check box.
ii. In the Callback URL box, since a callback URL will not be used for this application, enter a dummy but valid secured URL (https://) such as
https://login.salesforce.com/services/oauth2/callback. iii. In the Available OAuth Scopes list, select the following items:
l Access and manage your data (api)
l Full access (full)
l Perform requests on your behalf at any time (refresh_token, offline_access)
and click Add for each so that they appear in the Selected OAuth Scopes list.
c. Click Save.
6. In the page that appears for your new connected app, in the API (Enable OAuth Settings) section:
a. Copy the Consumer Key value and paste it in a secure reference document of your choice.
The Consumer Key is theclient_id.
b. Next to Consumer secret, click Click to reveal, copy the value that appears, and then paste it in your secure reference document.
The Consumer secret is theclient_secret. c. Save your reference document.
Note: You can always come back to this Salesforce page (Setup > App Setup > Create > Apps, and clicking the application name in the Connected Apps list).
7. Create a Salesforce permission set dedicated to the Coveo crawler and assign it to your dedicated app and user:
a. In the Setup page, select Manage Users > Permission Sets.
b. In the Permission Sets page, click New.
c. In the Create page, in the Label and API Name boxes, enter significant names, and then click Save.
d. In the page for the new permission set:
i. Click Manage Assignments, and then add the dedicated user you created earlier for the Coveo crawler (see"Creating a Dedicated Salesforce Crawling Account" on page 11).
ii. In the Apps section, click Assigned Connected Apps.
iii. In the Assigned Connected Apps section, click Edit, add the connected app you just created to the
Enabled Connected Apps list, and then click Save.
What's Next?
Create an ObjectsToGet Configuration file (see"Salesforce ObjectsToGet Configuration File" on page 19).
6. Salesforce ObjectsToGet Configuration File
The ObjectsToGet configuration file of the Salesforce connector contains the definition of all standard or custom objects that will be retrieved from the Salesforce organization. Each object definition is used to generate the SOQL query executed by the connector to retrieve the records for that object.
With this configuration file, you get control over:
l Which information is retrieved by specifying the fields and relationships that should be fetched for each object.
This information will be available to use in the mapping file.
l Which records are returned by specifying conditions on the SOQL query that will be used to filter the query results.
Notes:
l If you want to retrieve Salesforce Knowledge Base articles, you need to specify at least two queries for each type of Knowledge article, one for the*__kaobject and one the*__kavobject (see"Salesforce
ObjectsToGet Configuration File Example for Knowledge Base" on page 45).
l There is a bug in the Salesforce API that causes the returned JSON to be invalid when querying a binary field of an object, so ensure to not include any binary field in your query.
l CES 7.0.7914+ (October 2015)Support for the * character to replace a list of Objects and Parent relationship fields that are queryable.
Example: When the mapping file contains the following:
<Query>
<ObjectName>Case</ObjectName>
<Fields>
<string>*</string>
</Fields>
</Query>
You can use the following SOQL query:<Query value="Select * from Case" />
l CES 7.0.8047+ (December 2015)Support for the * character to replace a list of Child relationship fields that are queryable.
Example:<Query value="Select *,Parent.*, (Select * from Children) From Object/>
6.1 Salesforce Object Definition
To obtain the list of queryable fields on a specific object:
l Salesforce developers can use thedescribeSObject() methodto obtain the complete object definition in JSON format.
Example:https://na15.salesforce.com/services/data/v27.0/sobjects/Account/describe
l Salesforce administrators can obtain the complete list of fields from Salesforce API online documentation (see Account,Task).
To obtain the list of available relationships on a specific object:
l Salesforce administrators can access any object definition from Salesforce in the Setup under theCustomize menu. Object relationships are identified by fields of data typeLookup(seeAccountFields,TaskFields).
6.2 Configuration File Elements
The ObjectsToGet Salesforce configuration file is an aggregate of query XML nodes. A query node contains several elements, each one being used to generate the SOQL query of a Salesforce object.
Value attribute (optional) CES 7.0.7814+ (August 2015)
You can specify an SOQL query in the query value as shown in the following example (seeSalesforce Object Query Language (SOQL)):
<Query value="Select Id, Owner.Id, (Select Id From Shares) From Case Where CaseNumber>10" />
Keep in mind that only what is already in the objects to get is supported.
ObjectName (required)
The name of the object (standard or custom) to query (seeStandard Objects).
Note: If you are using thevalue attribute, the object name is optional and must be the same.
GroupBy (optional)
The name of the field on which results should be grouped by.
Limit (optional)
The maximum number of items that will be retrieved by the query.
Offset (optional)
The number of items that should be skipped in query results.
Fields (required)
Contains the name of the fields (Field Name column in Salesforce) that will be available on each record returned by the query. Each field name must be in a<string>element, no matter its data type. Fields specified in this section can be of any data type exceptLookup.
Example:
<Query>
<ObjectName>Account</ObjectName>
<Fields>
<string>Id</string>
<string>IsDeleted</string>
<string>Name</string>
<string>Type</string>
<string>BillingStreet</string>
<string>BillingCity</string>
<string>BillingState</string>
<string>BillingPostalCode</string>
<string>BillingCountry</string>
<string>Phone</string>
<string>Fax</string>
<string>AccountNumber</string>
<string>Website</string>
<string>Sic</string>
<string>Industry</string>
<string>AnnualRevenue</string>
<string>NumberOfEmployees</string>
<string>Ownership</string>
<string>TickerSymbol</string>
<string>Description</string>
<string>Rating</string>
<string>Site</string>
<string>CreatedDate</string>
<string>LastModifiedDate</string>
<string>SystemModstamp</string>
</Fields>
</Query>
QueryCondition (optional)
Important:CES 7.0.6942– (August 2014)This operator is not validated and has a free form. However, the resulting SOQL must be in the formatFIELD OPERATOR VALUE. Rather useQueryCondition2.
One or more conditions that will be applied to the SOQL query used to retrieve object records.
l Field(required):
Case-insensitive name of the object field on which the condition is applied. Relationship names can also be used (ex.: Parent.Type).
l Operator(required):
The operator to apply to the condition. Any operator supported by Salesforce SOQL queries can be used (seeComparison Operators).
l Value(required):
Case-sensitive value used to evaluate the condition. String values must be enclosed in single quotes.
Example:
<Query>
<ObjectName>Account</ObjectName>
<Fields>
<string>Name</string>
<string>AccountNumber</string>
</Fields>
<Conditions>
<QueryCondition>
<Field>Type</Field>
<Operator>!=</Operator>
<Value>'Prospect'</Value>
</QueryCondition>
<QueryCondition>
<Field>Owner.Name</Field>
<Operator>=</Operator>
<Value>'John Smith'</Value>
</QueryCondition>
</Conditions>
</Query>
The generated query is:
SELECT Name FROM Account WHERE Type != 'Prospect' AND Owner.Name = 'John Smith'
QueryCondition2 (optional)
Note: This query condition is validated and has more options. This is the prefered way to create a query condition.
One or more conditions that will be applied to the SOQL query used to retrieve object records.
l Field(required): Case-insensitive name of the Object Field on which the condition is applied. Relationship names can also be used (e.g.Parent.Type).
l Relation(required): The operator to apply to the condition. Supported operators areEqual,NotEqual, Less,LessOrEqual,Greater,GreaterOrEqual,Like,NotLike.
l SoqlString|SoqlBoolean|SoqlDateTime(required): Case-sensitive value (not Like) used to evaluate the condition.
Example:
<Query>
<ObjectName>Account</ObjectName>
<Fields>
<string>Name</string>
</Fields>
<Conditions>
<QueryCondition2>
<Field>Type</Field>
<Relation>NotEqual</Relation>
<SoqlString>Prospect</SoqlString>
</QueryCondition2>
<QueryCondition2>
<Field>IsEscalated</Field>
<Relation>Equal</Relation>
<SoqlBoolean>true</SoqlBoolean>
</QueryCondition2>
<QueryCondition2>
<Field>LastViewDate</Field>
<Relation>GreaterOrEqual</Relation>
<SoqlDateTime>2014-04-28T00:00:00.0000000-00:00</SoqlDateTime>
</QueryCondition2>
</Conditions>
</Query>
Note: ForSoqlDateTime, the date/time format must exactly matchYYYY-MM-DDTHH:MM:SS.0000000- 00:00
The generated query is:
SELECT Name FROM Account WHERE Type != 'Prospect' AND IsEscalated = true AND LastViewDate >= 2014- 04-28T00:00:00
InCondition (optional)
l Field(required): Case-insensitive name of the Object Field on which the condition is applied. Relationship names can also be used (e.g.Parent.Type).
l AllowedValues(required): Case-sensitive possible values of the field.
Example:
<Query>
<ObjectName>Account</ObjectName>
<Fields>
<string>Name</string>
</Fields>
<Conditions>
<InCondition>
<Field>Type</Field>
<AllowedValues>
<string>Prospect</string>
<string>Client</string>
</AllowedValues>
</InCondition>
</Conditions>
</Query>
The generated query is:
SELECT Name FROM Account WHERE Type IN ('Prospect', 'Client')
InQueryCondition (optional)
CES 7.0.7183+ (November 2014)Semi-joins are supported in query's conditions (seeComparison Operators).
Semi-joins are useful when you want to index only a subset of records based on another set of records.
l Field(required):
Case-insensitive name of the object field on which the condition is applied. Relationship names can also be used (ex.: Parent.Type).
l Query(required): A valid query object (withObjectName,Fields, etc) (seeSemi-Joins or Anti-Joins Relationship Query Limits).
Example:
<Query>
<ObjectName>Case</ObjectName>
<Fields>
<string>Id</string>
</Fields>
<Conditions>
<InCondition>
<Field>Id</Field>
<Query>
<ObjectName>CaseComment</ObjectName>
<Fields>
<string>ParentId</string>
</Fields>
<Conditions>
<QueryCondition>
<Field>CommentBody</Field>
<Operator>=</Operator>
<Value>'this is a test'</Value>
</QueryCondition>
</Conditions>
</Query>
</InCondition>
</Conditions>
</Query>
The generated query is:
SELECT Id FROM Case WHERE Id IN (SELECT ParentId FROM CaseComment WHERE CommentBody = 'this is a test')
Not InQueryCondition (optional)
CES 7.0.7183+ (November 2014)Anti-joins are supported in query's conditions (seeComparison Operators). Anti- joints are useful when you want to index only a subset of records based on another set of records.
l Field(required):
Case-insensitive name of the object field on which the condition is applied. Relationship names can also be used (ex.: Parent.Type).
l Query(required): A valid query object (withObjectName,Fields, etc) (seeSemi-Joins or Anti-Joins Query Limits).
Example:
<Query>
<ObjectName>Case</ObjectName>
<Fields>
<string>Id</string>
</Fields>
<Conditions>
<NotCondition>
<InCondition>
<Field>Id</Field>
<Query>
<ObjectName>CaseComment</ObjectName>
<Fields>
<string>ParentId</string>
</Fields>
<Conditions>
<QueryCondition>
<Field>CommentBody</Field>
<Operator>=</Operator>
<Value>'this is a test'</Value>
</QueryCondition>
</Conditions>
</Query>
</InCondition>
</NotCondition>
</Conditions>
</Query>
The generated query is:
SELECT Id FROM Case WHERE NOT Id IN (SELECT ParentId FROM CaseComment WHERE CommentBody = 'this is a test')
ParentRelationship (optional)
One or more relationships which information will be available on each object record returned by the query. An object relationship is defined by a lookup field which creates a relation between the current object being queried and another object. These relations allow SOQL query operations similar to SQL joins.
l RelationshipName(required):
The field name of data typeLookup.
l Fields(required):
The name of the fields of the related object that will be available on each record returned by the query.
l ParentRelationships(optional):
Another level of parent relationship, but this time, the relationship applies to the related object.
Example:
<Query>
<ObjectName>Account</ObjectName>
<Fields>
<string>Name</string>
<string>AccountNumber</string>
</Fields>
<ParentRelationships>
<ParentRelationship>
<RelationshipName>Owner</RelationshipName>
<Fields>
<string>Name</string>
<string>Email</string>
</Fields>
</ParentRelationship>
</ParentRelationships>
</Query>
Important:The parent field is copied to the record. If the parent is modified, the indexed record is not updated.
ChildRelationship (optional)
One or more relationships which information will be available on eachObjectrecord returned by the query. An Objectrelationship is defined by aLookup Fieldwhich creates a relation between the currentObjectbeing queried and anotherObject. These relations allow SOQL query operations similar to SQL joins.
l Query(required): A valid query object (withObjectName,Fields, etc).
Example:
<Query>
<ObjectName>Opportunity</ObjectName>
<Fields>
<string>Id</string>
<string>Name</string>
</Fields>
<ChildRelationships>
<Query>
<ObjectName>Attachments</ObjectName>
<Fields>
<string>Id</string>
<string>Name</string>
</Fields>
</Query>
</ChildRelationships>
</Query>
The generated query is:
SELECT Id, Name, (SELECT Id, Name FROM Attachments) FROM Opportunity
The generated metadata, when an attachment is found on the opportunity:
"Attachments.attribute.type" => "Attachment"
"Attachments.attribute.url" => "/services/data/v29.0/sobjects/Attachment/00PG000000B8RUvMAN"
"Attachments.Id" => "00PG000000B8RUvMAN"
"Attachments.Name" => "a_stash_of_werthers.jpg"
Note:
l When more than one child exist, the fields contain values separated with a semicolon.
Example:Attachments.Name: a.jpg;b.jpg
l Nested child relationships (sub-sub queries) are not supported.
Important:The child field is copied to the record. If a child is modified, the indexed record is not updated.
PolymorphicRelationship (optional)
Polymorphic relationships can be useful for parent relationships on aLookupfield that can be related to multiple types of objects (ex.: Lookup
(Contract,Campaign,Account,Opportunity,Product,Asset,Case,Solution)). The polymorphic relationship allows for different fields to be retrieved depending on the object that will be related for a specific record.
Notes:
l CES 7.0.8047+ (December 2015)Polymorphic relationships no longer depend on a parent relationship to work.
Example: You can add the following on feed items (TextPost,LinkPost,ContentPost,PollPost) to create theCreatedBy.SmallPhotoUrlmetadata when indexingFeedItem,FeedCommentand collaborationgroup:
<PolymorphicRelationship>
<RelationshipName>CreatedBy</RelationshipName>
<ObjectName>User</ObjectName>
<Fields>
<string>Name</string>
<string>Type</string>
<string>PhotoURL</string>
</Fields>
</PolymorphicRelationship>
l The two following metadata appear on the record with polymorphic relationships:<polymorphic_
relationship_name>.<field>and<polymorphic_relationship_name>_<object_
name>.<field>.
l CES 7.0.7104– (October 2014)The record with polymorphic relationships only provided the metadata named<polymorphic_relationship_name>_<object_name>.<field>.
l RelationshipName(required):
The field name of data typeLookup.
l ObjectName(optional):
The related object type this polymorphic relationship applies to.
Note:CES 7.0.7104– (October 2014)TheObjectNamefield is required.
l Fields(required):
The name of the fields of the related object that will be available on each record returned by the query.
l ParentRelationships(optional):
Another level of parent relationship, but this time, the relationship applies to the related object.
Example:
<Query>
<ObjectName>Task</ObjectName>
<Fields>
<string>Id</string>
<string>Subject</string>
<string>ActivityDate</string>
</Fields>
<ParentRelationships>
<ParentRelationship>
<RelationshipName>What</RelationshipName>
<Fields>
<string>Name</string>
<string>Type</string>
</Fields>
</ParentRelationship>
</ParentRelationships>
<PolymorphicRelationships>
<PolymorphicRelationship>
<RelationshipName>What</RelationshipName>
<ObjectName>Account</ObjectName>
<Fields>
<string>Name</string>
<string>AccountNumber</string>
</Fields>
</PolymorphicRelationship>
<PolymorphicRelationship>
<RelationshipName>What</RelationshipName>
<ObjectName>Opportunity</ObjectName>
<Fields>
<string>Amount</string>
<string>TotalOpportunityQuantity</string>
</Fields>
</PolymorphicRelationship>
</PolymorphicRelationships>
</Query>
Important:The parent field is copied to the record. If a parent is modified, the indexed record is not updated.
Order (optional)CES 7.0.6607+ (April 2014)
One or more order restrictions that will be applied to the SOQL query used to retrieve Object records.
l Ascending(optional): The direction of the ordering. Default istrue(ascending). Usefalsefor descending.
l NullsFirst(optional): Whether records withNULLvalues in the specified fields must be returned first or last. Default istrue.
l Fields(required): One or more fields to base the ordering on, in the specified field order.
Examples:
With the following configuration:
l Opportunity.Idshows that we can specify the query object name as the parent of the field.
l Account.Foo.Idis a field on the parentFoo, which is also a field of the parentAccountof Opportunity.
l What.Idis a field on the polymorphic parentWhatofOpportunity.
<Query>
<ObjectName>Opportunity</ObjectName>
<Fields>
<string>Id</string>
</Fields>
<Order>
<Ascending>true</Ascending>
<NullsFirst>false</NullsFirst>
<Fields>
<string>Name</string>
<string>Opportunity.Id</string>
<string>Account.Foo.Id</string>
<string>What.Id</string>
</Fields>
</Order>
</Query>
The generated query is:
SELECT Id FROM Opportunity ORDER BY Name, Opportunity.Id, Account.Foo.Id, What.Id ASC NULLS LAST
Configuration including a child relationship:
<Query>
<ObjectName>Opportunity</ObjectName>
<Fields>
<string>Id</string>
</Fields>
<ChildRelationships>
<Query>
<ObjectName>Attachments</ObjectName>
<Fields>
<string>Id</string>
</Fields>
<Order>
<Fields>
<string>Name</string>
</Fields>
</Order>
</Query>
</ChildRelationships>
</Query>
The generated query is:
SELECT Id, (SELECT Id FROM Attachments ORDER BY Name ASC NULLS FIRST) FROM Opportunity
6.3 XML Schema Definition
Note:CES 7.0.7183+ (November 2014)Each of the ObjectsToGet in your Salesforce sources are validated against the XSD.
If it is not the case, aSALESFORCE_INVALID_CONFIGURATIONerror message appears in the CES console and logs.
Use the following XML schema definition to validate your configuration file.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ArrayOfQuery" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Fields">
<xs:complexType>
<xs:sequence>
<xs:element name="string" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent msdata:ColumnName="string_Text" msdata:Ordinal="0">
<xs:extension base="xs:string">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ParentRelationships">
<xs:complexType>
<xs:sequence>
<xs:element name="ParentRelationship" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="RelationshipName" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element ref="Fields" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="ParentRelationships" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="ParentRelationship" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="RelationshipName" type="xs:string" minOccurs="0"
maxOccurs="1" />
<xs:element ref="Fields" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Query" type="QueryType" />
<xs:complexType name="QueryType">
<xs:sequence>
<xs:element name="ObjectName" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="GroupBy" type="xs:string" minOccurs="0" />
<xs:element name="Limit" type="xs:string" minOccurs="0" />
<xs:element name="Offset" type="xs:string" minOccurs="0" />
<xs:element name="Order" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Ascending" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element name="NullsFirst" type="xs:boolean" minOccurs="0" maxOccurs="1" />
<xs:element ref="Fields" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Conditions" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="QueryCondition" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Field" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="Operator" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="Value" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element ref="ParentRelationships" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="PolymorphicRelationships" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="PolymorphicRelationship" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="RelationshipName" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="ObjectName" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element ref="Fields" minOccurs="0" maxOccurs="unbounded" />
<xs:element ref="ParentRelationships" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ChildRelationships" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Query" type="QueryType" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfQuery" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:sequence>
<xs:element ref="Query" minOccurs="0" maxOccurs="unbounded">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
What's Next?
Create your ObjectsToGet configuration file (see"Creating a Salesforce ObjectsToGet Configuration File" on page 32).
6.4 Creating a Salesforce ObjectsToGet Configuration File
You must create an ObjectsToGet configuration file and attach it to your Salesforce source to instruct the connector which objects to retrieve from your Salesforce organization (see"Salesforce ObjectsToGet Configuration File" on page 19).
Note: You must be familiar with standard and custom objects and fields used in your Salesforce organization to be able to create a custom ObjectsToGet configuration file.
The content of the ObjectsToGet configuration file typically includes standard objects but most likely also the custom objects that you want to index. You can create your ObjectsToGet configuration file by starting with provided examples and customize it to suit your needs.
It is recommended to create separate ObjectsToGet configuration files with separate sources for the following types of Salesforce content:
l Service Cloud standard and custom objects and fields
l Knowledge base articles
l CRM Content
To create a Salesforce ObjectsToGet configuration file
1. Refer to the most appropriate of the following topics to copy the content of the corresponding ObjectsToGet XML configuration file example:
l Salesforce ObjectsToGet Configuration File Example for Standard Objects
l "Salesforce ObjectsToGet Configuration File Example for Knowledge Base" on page 45
l "Salesforce ObjectsToGet Configuration File Example for CRM Content " on page 48
2. Using a text editor:
a. Paste the content of the ObjectsToGet configuration file example.
b. Modify or remove standard objects and fields, or add custom objects and fields to match the needs of your Salesforce organization (see"Salesforce ObjectsToGet Configuration File" on page 19).
c. Save your ObjectsToGet configuration file.
3. Validate your ObjectsToGet configuration file (see"XML Schema Definition" on page 30).
4. Using an administrator account, connect to the Coveo Master server, and copy your custom ObjectsToGet configuration file to a location accessible to CES.
Example: On the Coveo Master server, for an ObjectsToGet configuration file for standard and custom objects and fields, save the file as:
D:\CES7\Config\Salesforce_Basic_ObjectsToGet.xml.
You will specify the full path to this file when you configure your Salesforce source (see"ObjectsToGet File" on page 91).
What's Next?
Create a mapping file to transfer the values of fields retrieved from Salesforce into CES fields (see"Creating a Salesforce Mapping File" on page 65).
6.5 Salesforce ObjectsToGet Configuration File Example for Standard Objects
The ObjectsToGet configuration file example presented in this topic specifies to retrieve the following standard Service Cloud objects and fields (including Chatter feed items) that are typically useful to index:
l Account
l Case
l Case Comment
l Contact
l Event
l Solution
l Task
l User
l Attachment
l Feed item (Chatter)CES 7.0.6196+ (November 2013)
l Feed comment (Chatter)CES 7.0.6196+ (November 2013)
The following code sample is the content of the ObjectsToGet configuration file example for standard Service Cloud objects and fields.
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfQuery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Query>
<ObjectName>Account</ObjectName>
<Fields>
<string>Id</string>
<string>IsDeleted</string>
<string>Name</string>
<string>Type</string>
<string>BillingStreet</string>
<string>BillingCity</string>
<string>BillingState</string>
<string>BillingPostalCode</string>
<string>BillingCountry</string>
<string>Phone</string>
<string>Fax</string>
<string>AccountNumber</string>
<string>Website</string>
<string>Sic</string>
<string>Industry</string>
<string>AnnualRevenue</string>
<string>NumberOfEmployees</string>
<string>Ownership</string>
<string>TickerSymbol</string>
<string>Description</string>
<string>Rating</string>
<string>Site</string>
<string>CreatedDate</string>
<string>LastModifiedDate</string>
<string>SystemModstamp</string>
<string>LastActivityDate</string>
<string>Jigsaw</string>
<string>JigsawCompanyId</string>
<string>AccountSource</string>
<string>SicDesc</string>
</Fields>
<ParentRelationships>
<ParentRelationship>
<RelationshipName>MasterRecord</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Parent</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Owner</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>CreatedBy</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>LastModifiedBy</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
</ParentRelationships>
</Query>
<Query>
<ObjectName>Case</ObjectName>
<Fields>
<string>Id</string>
<string>IsDeleted</string>
<string>CaseNumber</string>
<string>SuppliedName</string>
<string>SuppliedEmail</string>
<string>SuppliedCompany</string>
<string>Type</string>
<string>Status</string>
<string>Reason</string>
<string>Origin</string>
<string>Subject</string>
<string>Priority</string>
<string>Description</string>
<string>IsClosed</string>
<string>ClosedDate</string>
<string>IsEscalated</string>
<string>SystemModstamp</string>
</Fields>
<ParentRelationships>
<ParentRelationship>
<RelationshipName>Contact</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Account</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Asset</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Parent</RelationshipName>
<Fields>
<string>CaseNumber</string>
<string>Subject</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Owner</RelationshipName>
<Fields>
<string>Name</string>
<string>Type</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>CreatedBy</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>LastModifiedBy</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
</ParentRelationships>
<PolymorphicRelationships>
<PolymorphicRelationship>
<RelationshipName>Owner</RelationshipName>
<ObjectName>Group</ObjectName>
</PolymorphicRelationship>
<PolymorphicRelationship>
<RelationshipName>Owner</RelationshipName>
<ObjectName>User</ObjectName>
</PolymorphicRelationship>
</PolymorphicRelationships>
</Query>
<Query>
<ObjectName>CaseComment</ObjectName>
<Fields>
<string>Id</string>
<string>IsPublished</string>
<string>CommentBody</string>
<string>CreatedDate</string>
<string>SystemModstamp</string>
<string>LastModifiedDate</string>
<string>IsDeleted</string>
</Fields>
<ParentRelationships>
<ParentRelationship>
<RelationshipName>Parent</RelationshipName>
<Fields>
<string>CaseNumber</string>
<string>Subject</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>CreatedBy</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>LastModifiedBy</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
</ParentRelationships>
</Query>
<Query>
<ObjectName>Contact</ObjectName>
<Fields>
<string>Id</string>
<string>IsDeleted</string>
<string>LastName</string>
<string>FirstName</string>
<string>Salutation</string>
<string>Name</string>
<string>MailingStreet</string>
<string>MailingCity</string>
<string>MailingState</string>
<string>MailingPostalCode</string>
<string>MailingCountry</string>
<string>Phone</string>
<string>Fax</string>
<string>MobilePhone</string>
<string>HomePhone</string>
<string>AssistantPhone</string>
<string>Email</string>
<string>Title</string>
<string>Department</string>
<string>AssistantName</string>
<string>LeadSource</string>
<string>Birthdate</string>
<string>Description</string>
<string>CreatedDate</string>
<string>LastModifiedDate</string>
<string>SystemModstamp</string>
<string>LastActivityDate</string>
<string>Jigsaw</string>
<string>JigsawContactId</string>
</Fields>
<ParentRelationships>
<ParentRelationship>
<RelationshipName>MasterRecord</RelationshipName>
<Fields>
<string>Name</string>
</Fields>
</ParentRelationship>
<ParentRelationship>
<RelationshipName>Account</RelationshipName>
<Fields>
<string>Name</string>