10

I have to get all the "linked" records from a Document (ContentDocument) and then filter only the Events from them using the following apex.

// Query ContentDocumentLink object for the 'Event' link and apply 'WHERE' filter of the above map's contentdocument id.
Map<id, Event> mapEvent = new Map<id, Event>();
Set<Id> EventIds = new Set<Id>();
for(ContentDocumentLink cdlForEvent: [SELECT ContentDocumentID, LinkedEntity.type, LinkedEntityId 
                                    FROM ContentDocumentLink 
                                    WHERE ContentDocumentID IN: mapOfContentVersion.keySet()])
{
    if(cdlForEvent.LinkedEntity.Type == 'Event')
    {
        EventIds.add(cdlForEvent.LinkedEntityId);
    }
}

I'm using ContentDocumentId filter, from a contentversion map but it is giving me following error

Implementation restriction: ContentDocumentLink requires a filter by a single Id on ContentDocumentId or LinkedEntityId using the equals operator or multiple Id's using the IN operator.

Interestingly, if I provided hard-coded values using IN clause then it accepts it. But I have to make it run in the apex and it has to be dynamic. Following soql works

for(ContentDocumentLink cdlForEvent: 
                [SELECT ContentDocumentID, LinkedEntity.type, LinkedEntityId 
                FROM ContentDocumentLink 
                WHERE ContentDocumentID IN ('06923000000CqHNaxy', '06923000000CqHNAA0')])

I dont understand what is missing. How should I get all the related linked entity records and then filter Events from them?

1
  • Can you log the value of mapOfContentVersion.keySet() - what does it return? – Gaurav Kheterpal Jun 22 '16 at 13:17
21

the solution is to add your keySet() from Map to a new Set() and use that in the query filter using IN:

Ex:

Set<Id> newSet = mapOfContentVersion.keySet();


[SELECT ContentDocumentID, LinkedEntity.type, LinkedEntityId 
                                    FROM ContentDocumentLink 
                                    WHERE ContentDocumentID IN: newSet ]

**This worked for me today

3
  • It does but why? map.keySet() and a set<id> , aren't they both same thing? – Mahmood Jun 24 '16 at 5:37
  • 1
    In a unit test, this works only if you execute the query one time but not two times before StartTest. The second time I get the same error. After StopTest I can query again filtering by the new set without issues. Does anyone have any idea why this is happening? – sebascanseco Feb 24 '18 at 17:14
  • Not sure how this one works, didn't work for me unfortunately. Exec. Anonymous Code: Map<Id, ContentVersion> mapCV = new Map<Id, ContentVersion>(); Set<Id> setId = mapCV.keyset(); List<ContentDocumentLink> listCDL = [SELECT LinkedEntityId, ContentDocumentId, Visibility FROM ContentDocumentLink WHERE ContentDocumentId IN: setId]; – Pasan Eeriyagama Apr 16 at 3:42
7

This must be a recent update (this year), because I had code working filtering on a Set with no problem, and suddenly noticed today it no longer worked. I resolved the issue by first casting the Set to a List; see below.

    // Get content document links
    List<ContentDocumentLink> contentDocLinks = [
        SELECT
            ContentDocumentId
        FROM
            ContentDocumentLink
        WHERE
            LinkedEntityId IN :stipRecordIds
    ];
    Set<Id> contentDocIds = new Set<Id>();
    for(ContentDocumentLink contentDocLink : contentDocLinks) {
        contentDocIds.add(contentDocLink.ContentDocumentId);
    }
    List<Id> contentDocIdList = new List<Id>(contentDocIds);

    // Get the actual files
    List<ContentVersion> contentVersions = [
        SELECT
            Id,
            ContentUrl
        FROM
            ContentVersion
        WHERE
            ContentDocumentId IN :contentDocIdList
            AND
            IsLatest = True
    ];
1
  • I believe this is something with Content specific objects. See my comments above to Cropredy's reply. Never worked for me until I changed it to List<id>. – Mahmood Oct 20 '16 at 19:57
6

In addition to @harish answer, the underlying problem is similar to using object.field notation as bind variables in dynamic SOQL - even though the use case is static SOQL

For static SOQL - does not work

[select COUNT() from ContentDocumentLink where LinkedEntityId = :someObj.Id]

For static SOQL, does work

ID filter = someObj.ID;
[select COUNT() from ContentDocumentLink where LinkedEntityId = :filter]

That is, filter works because it is a simple variable and not located via an object reference (e.g. someObj.Id)

1
  • recently I encountered another very weird issue where I was not getting results for map.keySet() or Set<id> even if I put them in a variable but it worked for List<id>. :-) – Mahmood Sep 28 '16 at 6:45
5

I encountered the same error in my query for ContentDocumentLink records:

"Implementation restriction: ContentDocumentLink requires a filter by a single Id on ContentDocumentId or LinkedEntityId using the equals operator or multiple Id's using the IN operator."

But the issue turned out to be that my Set was empty. The error message was misleading.

I resolved the issue by checking if my Set had values before proceeding with the query for ContentDocumentLinks.

As an example:

Set<Id> newSet = mapOfContentVersion.keySet();
if(EventIds.size() > 0){
     [SELECT ContentDocumentID, LinkedEntity.type, LinkedEntityId 
                                    FROM ContentDocumentLink 
                                    WHERE ContentDocumentID IN: newSet ]
}
0

I'm not sure if this top voted answer workaround is valid anymore. It didn't work for my below Exec. anonymous code. Feel free to copy-paste and try.

Map<Id, ContentVersion> mapCV = new Map<Id, ContentVersion>();
Set<Id> setId = mapCV.keyset();
List<ContentDocumentLink> listCDL = [SELECT LinkedEntityId, ContentDocumentId, Visibility 
                                     FROM ContentDocumentLink WHERE ContentDocumentId IN: setId];

Below is another working solution,

List<ContentDocumentLink> listCDL = new List<ContentDocumentLink>();

if (!mapCV.isEmpty()){

listCDL = [SELECT LinkedEntityId, ContentDocumentId, Visibility FROM ContentDocumentLink WHERE ContentDocumentId IN: mapCV.keySet()];

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.