Salesforce Notes is a feature that let’s you add Notes on almost any Salesforce Record. In Salesforce Classic, they used to be simply Notes, but now in Salesforce Lightning, they upgraded to Enhanced Notes which can include rich text, lists and images and relate notes to more than one record.
This upgrade of course comes with a different structure. You can’t simply query notes by looking into the Notes sObject. While the Classic notes were stored in the Note sObject and its respective attachments were stored in the Attachment sObject; the new Lightning Enhanced Notes are stored in the Content object with a host of other sObjects (ContentDocument
, ContentVersion
, ContentDocumentLink
, and ContentNote
) to go with and are accessed differently.
I came across this problem while trying to find some orphan Notes, which in the end were simply erroneously placed in Classic Notes instead of Lightning Enhanced Notes sObject. (See: How to Migrate Salesforce Classic Notes to Lightning Enhanced Notes).
Query Classic Salesforce Notes
You can query Classic Notes and it will bring the attachments as well.
List<Note> notes = [SELECT Id FROM Note WHERE ParentId = :mysampleRecord];
List<Attachment> attachments = [SELECT Id FROM Attachment WHERE ParentId = :mysampleRecord];
Pretty straightforward, right?
Salesforce Lightning Notes Structure
In Lightning, the sObject Content (which hosts Notes) has a different structure and it’s more complex. Notes and Attachments are represented by the ContentDocument
sObject, which acts as a Parent object and hosts the versions of these attached files and Notes on possibly multiple linked ContentVersion
records.
ContentDocument
records stores the link to all the records Notes and Attachments are related to with entries on the ContentDocumentLink
sObject. (see: How to relink/unlink Notes to records)
The structure can get even more complicated with the existence of ContentNote
, which acts as a facade object for ContentDocument
but with only one ContentVersion
in its Content
field. You only use this ContentNote
sObject when you’re adding new Notes.
Query Salesforce Lightning Notes
To query Notes and Attachments in Lightning for some object whose Id is mysampleRecord
:
List<ContentDocumentLink> cdls = [SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :myRecord];
Set<Id> documentIds = new Set<Id>();
for (ContentDocumentLink cdl : cdls) {
documentIds.add(cdl.ContentDocumentId);
}
// ContentDocumentLink doesn't support semi-joins, which is frustrating.
List<ContentDocument> documents = [SELECT Id FROM ContentDocument WHERE Id IN :documentIds];
This query will bring ContentNote
and regular ContentDocument
Attachments.
If you’re only looking for Notes, you can query ContentNote
sObject only. For ContentNote
, request the Content
field in your ContentNote
query.
If you want just Attachments and not Notes, filter with FileType != 'SNOTE'
.
To query the actual content of the Notes, for ContentDocument
, query ContentVersion
against ContentDocumentId
and add IsLatest = true
.
To query Notes with their Attachments, then use the following query:
SELECT ID
,Name
,(SELECT RecordType
FROM CombinedAttachments AS S
WHERE S.RecordType = 'Note'
OR S.RecordType = 'Attachment'
)
FROM Account
You can replace Account with any other sObject that the notes are attached to and you’d like to query from.
How to Query Notes linked to Accounts
SELECT Id, ContentDocumentId, ContentDocument.Title,
LinkedEntityId, LinkedEntity.Name
FROM ContentDocumentLink
WHERE LinkedEntityId IN (
SELECT Id
FROM Account
)