I am trying to fetch Knowledge Articles based on Data Category through the below dynamic Soql query.

String dynamicQuery = 'SELECT Id, Title FROM Knowledge__kav ' +
                                        'WHERE PublishStatus = \'Online\' ' +
                                        'WITH DATA CATEGORY Topics__c AT ({0})';

List<Knowledge__kav> kavList = Database.query(String.format(dynamicQuery, DynamicTopics));

Wherein 'DynamicTopics' is a list of String having the data category name.

The problem i am facing here is, i get all the articles without distinguishing which data category it belongs to.

I cannot put this in for loop as it might hit the limit.

I want the article to be fetched along with their data category or something from which i can distinguishing it with the data category

Can you please help me with this?

  • This is a limitation of the platform. You're going to have to work within the limits. You shouldn't present a situation where this could be a problem.
    – sfdcfox
    Dec 28, 2018 at 9:31
  • @sfdcfox that's what the problem statement is.. i am not able to find a solution. Dec 28, 2018 at 10:18

2 Answers 2


You need to use ArticleType_DataCategorySelection object to retrieve ParentId (which is Article Id) and DataCategory Names.

Here is an example from my DE where ArticleType is Documentation_Kav

SELECT Id, ParentId, Parent.Title, DataCategoryGroupName, DataCategoryName 
FROM Documentation__DataCategorySelection
WHERE Parent.PublishStatus = 'Online'

By the way, DataCategoryName cannot be filtered in SOQL query, this is Salesforce Limitation

Like, we cannot execute this query

SELECT Id, ParentId, Parent.Title, DataCategoryGroupName, DataCategoryName 
FROM Documentation__DataCategorySelection
WHERE Parent.PublishStatus = 'Online'
AND DataCategoryName IN ('ABC', 'XYZ')

For more information, refer Article Type__DataCategorySelection

  • Hi Santanu,.. there are too many records in my knowledge_DatacategorySelection object. the reason i dint use this object because i would hit the limit as i will have to fetch all the knowledge articles without any filters. Dec 28, 2018 at 11:53

I have managed to recover the structure of the hierarchy for each group based on the following documentation: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_describedatacategorygroupstructures.htm https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_class_Schema_DescribeDataCategoryGroupStructureResult.htm

The method would be the following, where dataCategoryGroupName contains the name of the corresponding group and the result of the hierarchy is printed in the variable "results", with the default structure and putting it inside a wrapper in the variable "dataCategoryStructure"

    public static void describeDataCateogryGroupStructuresSample(String dataCategoryGroupName) {
    // Create the data category pairs
    DataCategoryGroupSobjectTypePair pair1 = new DataCategoryGroupSobjectTypePair();
    //DataCategoryGroupSobjectTypePair pair2 = new DataCategoryGroupSobjectTypePair();
    DataCategoryGroupSobjectTypePair[] pairs = 
    new DataCategoryGroupSobjectTypePair[] {
    //, pair2
    // Get the list of top level categories using the describe call
    DescribeDataCategoryGroupStructureResult[] results =
    system.debug('*** results: ' +JSON.serializePretty(results));
    List<CategoryInfo> dataCategoryStructure = new List<CategoryInfo>();
    // Iterate through each result and get some properties
    // including top categories and child categories
    for (Integer i = 0; i < results.size(); i++) {
        DescribeDataCategoryGroupStructureResult result = 
        //String sObjectObj = result.getSobject();

        system.debug('*** Group name: ' + result.getName());
        system.debug('*** Group label: ' + result.getLabel());
        system.debug('*** Group description: ' + result.getDescription());
        // Get the top-level categories
        DataCategory[] topCategories = result.getTopCategories();
        // Iterate through the top level categories and retrieve 
        // some information
        for (Integer j = 0; j < topCategories.size(); j++) {
            DataCategory topCategory = topCategories[j];
            system.debug('*** Category name: ' + topCategory.getName());
            system.debug('*** Category label: ' + topCategory.getLabel());
            system.debug('*** Child categories: ' + JSON.serializePretty (topCategory.getChildCategories()));
            CategoryInfo ci = new CategoryInfo();
            ci.Name = topCategory.getName();
            ci.Label = topCategory.getLabel();
            ci.listChildCategory = new List<CategoryInfo>();
            DataCategory [] childCategories = topCategory.getChildCategories();
            for (Integer k = 0; k < childCategories.size(); k++) {          
                system.debug('*** Child Category name: ' + childCategories[k].getName());
                system.debug('*** Child Category label: ' + childCategories[k].getLabel());
                system.debug('************** ');
                CategoryInfo ciChild = new CategoryInfo();
                ciChild.Name = childCategories[k].getName();
                ciChild.Label = childCategories[k].getLabel();
                ciChild.listChildCategory = new List<CategoryInfo>();
                DataCategory [] grandChildCategories = childCategories[k].getChildCategories();
                for (Integer l = 0; l < grandChildCategories.size(); l++) {         
                    system.debug('*** Grand Child Category name: ' + grandChildCategories[l].getName());
                    system.debug('*** Grand Child Category label: ' + grandChildCategories[l].getLabel());
                    system.debug('************** ');
                     CategoryInfo ciGrandChild = new CategoryInfo();
                    ciGrandChild.Name = grandChildCategories[l].getName();
                    ciGrandChild.Label = grandChildCategories[l].getLabel();
                    ciGrandChild.listChildCategory = new List<CategoryInfo>();
                    DataCategory [] superGrandChildCategories = grandChildCategories[l].getChildCategories();
                    for (Integer m = 0; m < superGrandChildCategories.size(); m++) {            
                        system.debug('*** Grand Child Category name: ' + superGrandChildCategories[m].getName());
                        system.debug('*** Grand Child Category label: ' + superGrandChildCategories[m].getLabel());
                        system.debug('************** ');
                        CategoryInfo ciSuperGrandChild = new CategoryInfo();
                        ciSuperGrandChild.Name = superGrandChildCategories[m].getName();
                        ciSuperGrandChild.Label = superGrandChildCategories[m].getLabel();
                        //ciSuperGrandChild.listChildCategory = new List<CategoryInfo>();
    system.debug('*** dataCategoryStructure: ' +JSON.serializePretty(dataCategoryStructure));

public class CategoryInfo
    public String Name;
    public String Label;
    public List<CategoryInfo> listChildCategory;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .