Didn't understand relationship 'LinkedEntityId' in field path - salesforce

So I am generally able to query the relationships but I do not have the access to this object in object manager, so what should be the query to access accountId from ContentDocumentLink object when I know LinkedEntity is a case.
My Code:
List<ContentDocumentLink> case_file_links=
[
SELECT Id,ContentDocumentId,LinkedEntityId.AccountId,ShareType
FROM ContentDocumentLink
WHERE Id IN: case_file_link_Ids
];
Error:
SELECT Id,ContentDocumentId,LinkedEntityId.AccountId,ShareType
^
ERROR at Row:2:Column:45
Didn't understand relationship 'LinkedEntityId' in field path. If you..

LinkedEntityId is a weird mutant lookup to many tables, any table that supports File upload. Official name is "polymorphic lookup".
Maybe you worked with Tasks before, they have similar fields. WhatId can point to Account, Case, Opportunity plus many custom objects. and WhoId points to User/Contact/Lead.
So it's a lookup to "something". It's not guaranteed it's to Cases so at compile time SF can't just blindly accept AccountId. What if the field is not there.
You might have to use TYPEOF in SOQL.
SELECT Id, ContentDocumentId, ShareType,
TYPEOF LinkedEntity WHEN Case THEN CaseNumber, Subject, AccountId END
FROM ContentDocumentLink
WHERE Id IN ('06A7a000001VafmEAC', '06A7a000001VafnEAC')
Developer Console is too stupid to display it properly but workbench should manage
In Apex you'll need an instanceof to check and cast the LinkedEntity to right sObject... or use the generic sObj.get('AccountId') and if it's not there it'll return null?
If this sounds like too much hassle - you can always split it into 2 queries.
Query just SELECT Id, ContentDocumentId, LinkedEntityId, ShareType FROM ContentDocumentLink
Loop through results, collect LinkedEntityId into a helper Set<Id>.
Map<Id, Case> cases = new Map<Id, Case>([SELECT Id, AccountId FROM Case WHERE Id IN :mySet]);

Related

Query of records based on relationships

I have an object Contract that has a look-up to another object Indexationtype. I have another object IndexationEntry that has master-detail to Indexationtype. Now I would like to get the value of the percentage field in the IndexationEntry onto Contract based on the yer fields. The year in the IndexationEntry matches Year in Contract. How should I achieve this?
From Contract "up" to IndexationType__c, then "down" to IndexationEntry__c?
If there's no direct link between them it's not going to be pretty. One way would be something like this
SELECT Id, Name,
(SELECT Id, ContractNumber FROM Contracts__r WHERE Year__c = '2021'),
(SELECT Id, Percent__c FROM IndexationEntries__r WHERE Year__c = '2021')
FROM IndexationType__c
You'd have to run it once for each year. Or (since you tagged it Apex) maybe you can prepare the reference data a bit, query Indexation Types + Entries and build something like Map<Id, Map<Integer, IndexationEntry__c>> (1st key is by Indexation Type Id, then by year). Query them, populate the Map, then loop through your contracts and use map.get() to fetch your values.

How to query all task which are having relatedto(whatId) as Account or Contact

I am using an soql query to get tasks. My requirement is to get all tasks which are related account or contact object. Also few other fields inside Account or contact object whichever the object related. Is there a simple way instead of writing multiple queries.
Please provide more specific information next time. Generally speaking you can refer to a parent object by reference name followed with a dot. Here is an example
Select Account.Name, AccountId From Task Where Account.Name = 'John'
Here Account is the name of the reference (from task) and AccountId is the referencing field.
Your question is a little unclear. Are you looking for all TASKS related to any ACCOUNT or CONTACT or related to specific ACCOUNTS or CONTACTS?
If the former, try
SELECT Id, Subject,
FROM TASK
WHERE
What.Type = 'Account' OR
Who.Type = 'Contact'
if the latter, use the IN :list syntax already suggested by Moti. The What.Type is useful, as opposed to AccountId!=null, because it will not return TASKS associated with, for example, OPPORTUNITIES (if you want that behavior, use AccountId!=null and maybe drop the Who.Type if you associate all CONTACTS with OPPORTUNITIES, as it would be redundant).
In either case, your issue will be pulling specific data from CONTACT whos, as polymorphic fields only allow access to a limited number of fields. Can't seem to find that list right now. I don't believe old SOQL supports the kind of the syntax to do that in one query--that's why SOQL polymorphism made such a bang--though I could be wrong.
Now, if you have SOQL TYPEOF available to you, you should be able to do something more interesting like:
SELECT Id, Subject,
TYPEOF What
WHEN Account THEN AccountNumber
END,
TYPEOF Who
WHEN Contact THEN FirstName
END
FROM Task
WHERE
What.Type = 'Account' OR
Who.Type = 'Contact'
How about
select {column list] from task where parentid in (select id from account where ...) or parentid in (select id from contact where ...)
Alternatively, if you're inside Apex and already have the contact or account ids in a list (we'll use idList), you can use:
select {column list] from task where parentid in :idList

Selecting custom fields of "who" object using SOQL gives no such column error

I am looking for select custom fields of "who" object using SOQL in slaesforce:
As I am testing following SOQL, its working fine.
Select t.Who.FirstName, t.Status From Task t Where t.ActivityDate = TODAY AND t.Who.Type = 'Lead'
but while add any custom field of lead object(who object here) in select statement, as mentioned following query, its give error as
No such column 'LeadExtraInfo__c' on entity 'Name'.
even LeadExtraInfo field exist into Lead object
Select t.Who.FirstName, t.Who.LeadExtraInfo__c t.ActivityDate From Task t Where t.ActivityDate = YESTERDAY AND t.Who.Type = 'Lead'
The Who and What relationships on Task are not normal relationships -- they are polymorphic. This means that they can refer to different types of objects.
In the case of Who, it can refer to a Lead or a Contact. As such, you can only get to a limited subset of the fields in the relationship, namely the ones mentioned in this doc page.
To get to other fields on Lead, you'll have to query the Task first to get its WhoId, then query Lead where the Id equals that WhoId value to get those other fields.

Ordering and Limiting A Subquery In Salesforce SOQL

I am attempting to retrieve the owner of a case, based on a partial match, where we choose the most recent case that matches the partial match.
This is the query I am attempting:
SELECT User.CustomField__c
FROM User
WHERE User.Id IN (
SELECT OwnerId
FROM Case
WHERE Case.CaseNumber LIKE '%1026'
ORDER BY Case.CreatedDate DESC LIMIT 1)
The following query works on its own, but doesn't seem happy as part of the subquery:
SELECT OwnerId
FROM Case
WHERE Case.CaseNumber LIKE '%1026'
ORDER BY Case.CreatedDate DESC LIMIT 1
Equally, if I drop the ORDER BY and LIMIT it works:
SELECT User.NVMContactWorld__NVM_Agent_Id__c
FROM User
WHERE User.Id IN (
SELECT OwnerId FROM Case
WHERE Case.CaseNumber LIKE '%1026')
Are order / limit queries not allowed in a SOQL subquery?
Just to clarify this issue, the scenario I am dealing with looks like this...
A Salesforce organisation can configure the "display format" for Case Numbers. If they select "4" digits, you get case numbers like:
0001
0125
1234
33456
It is possible to reconfigure your case numbers to get the following case numbers as well as the case numbers above...
000001
001234
033456
I didn't want people to be confused by the LIKE statement, the issue is that 001234 and 1234 are different cases, so if a customer supplies 1234 and I find two records, I want to start off assuming that they are the most recent case.
So either consider the LIKE statement or an IN statement that contains ('001234', '1234')
There is no documentation I could find that specifies that LIMIT and/or ORDER BY do not work with subqueries, but I ran into the same error you mentioned.
However, it may work to start at the Case object and look up to the User, similar to the Lookup Relationships and Outer Joins section in the SOQL documentation. I'm not sure if this would work for you, but it's something you may want to try.
Here's an example:
-- Edit --
SELECT OwnerId, Owner.CustomField__c
FROM Case WHERE
CaseNumber LIKE '%1026'
ORDER BY CreatedDate DESC
LIMIT 1
Turns out Custom Fields are not accessible because OwnerId is a polymorphic key referencing either Group or User. That means the above won't work, sorry.
To work-around this is very complicated. You would have to create a custom lookup field called "User Owner", or something. That would store a lookup reference to the User, if the Owner is a User (this can be checked by comparing the beginning of OwnerId to '005', the User ID prefix). That field would need to be populated using a after insert, after update Trigger. All values for this new field would need to be dataloaded for previously existing Cases. But, once you have this new "User Owner" field, you can access custom fields on User through SOQL, using it.
ORDER BY and LIMIT don't make sense in your subquery because you're not returning records from the subquery. Instead, the subquery just builds a list of IDs used to filter the main query.
If you use a subquery in a way that the subquery records are returned, these clauses are fine. For example, this works:
SELECT Name,
(SELECT FirstName, LastName FROM Contacts ORDER BY LastName LIMIT 10)
FROM Account
I think it's worth adding that with new features of SOQL that were not available when this question was first asked and answered, that the approach of querying from Case should now be viable (with access to custom fields).
In particular the TYPEOF feature provides access to type specific fields through polymorphic lookups: http://www.salesforce.com/us/developer/docs/soql_sosl/Content/sforce_api_calls_soql_select_typeof.htm
It is worth noting that this feature is still in Developer Preview.
SELECT
TYPEOF Owner
WHEN User THEN CustomField__c
END
FROM CASE
Did you try switching your query around to be something like this?
SELECT OwnerId, (select id from user)
FROM Case
WHERE Case.CaseNumber LIKE '%1026'
ORDER BY Case.CreatedDate DESC LIMIT 1

SOQL query to traverse several levels on Task

I'm trying to write some apex code using this query and not getting anywhere:
List<Task> tasks = [SELECT id, whatid, who.account.parent.name FROM task WHERE who.account.parent.name LIKE 'Procter%'];
I'm not surprised this doesn't work, but can't seem to find documentation anywhere that explains how I would go about this. Does anyone have any idea? I'm trying to get all tasks linked to a contact linked to an account with a parent account of "procter and gamble"...
Looks like the options to "go up" in the mixed fields (the ones where Lookup goes to multiple objects like WhatId going to Account or Opportunity) are very limited. I was able to write "WHERE what.name LIKE 'Procter%' but not "WHERE what.parent.name LIKE 'Procter%'".
By the way I think it should be WhatId and not the WhoId (check out the Validation Rule editor for Tasks, try to insert fields "Contact/Lead ID" and "Opportunity/Account ID"). You will also see that you can't "go up" (or in case of this editor - "go right") on these fields while for some other fields you can explore the relation like for "CreatedBy.UserRole.Name".
Can you try this subquery instead?
[SELECT id, whatid FROM task WHERE whatid IN (SELECT Id FROM Account WHERE Parent.Name LIKE 'United%')]
WhatId and WhoID are polymorphic fields, so these fields do not support traversing multiple levels.
I had a similar requirement for hierarchal traversing, in my case i had to select the lead information associated with a task. What I had to do was first query for a list of tasks, then query for a list of leads based off those tasks, then use a wrapper class to combine the two lists into a custom object and display the object accordingly using visualforce. The wrapper class was certainly my answer to the equation since it seems you are in fact unable to query directly using the Who.Id.
Hope this helps!
The AccountID field on Tasks is populated by SF automatically for Contacts. Obviously, it is blank for Leads. So, if you want to get Account data you can just do something like this:
SELECT ID, Who.FirstName, Who.LastName, Account.Parent.Name FROM Task WHERE WhoID = '00Q12SDFUUALDLKJF'
Obviously, Account.Parent.Name is blank for Leads.

Resources