Sitecore Integrated Graphql – passing search filtering parameters

I was recently spending some time on the sitecore headless approach for delivering content to various devices and channels.

In the headless approach we can render the JSON payload using sitecore layout service https://jss.sitecore.com/docs/fundamentals/services/layout-service .

Within each sitecore rendering we can either use the out for the box rendering resolver or custom rendering resolver to format the response for individual components.We can also use the approach of integrated / connected graphql approach for rendering the JSON response for the individual renderings.

https://jss.sitecore.com/docs/fundamentals/services/graphql

https://doc.sitecore.com/developers/100/sitecore-experience-manager/en/graphql.html

One of the need was to search the content in the sitecore and sitecore graphql has already a basic implementation of  Content Search API, designed to fulfill the needs of keyword searching.

https://doc.sitecore.com/developers/100/sitecore-experience-manager/en/the-graphql-content-schema.html- look for content search API section.

We can even pass the pass filtering parameter to filter the returned results.

Below article from Adam has detailed explanation with an example of how we can implement the search functionality in few steps without much effort. We can pass the filtering tags as parameters/variables from the client application dynamically to the to the graphql endpoint to fitter the search results.

search(first: Int = nullafter: StringrootItem: String = nullkeyword: String = nulllanguage: String = nulllatestVersion: Boolean = trueindex: String = nullfieldsEqual: [ItemSearchFieldQuery] = nullfacetOn: [String!] = null): ContentSearchResults

https://www.adamlamarre.com/implementing-a-search-page-with-sitecore-jss/

There is no out of box the way to pass the filtering parameter to the graphql query when we use the integrated graphql mode. However we have an option to send the custom variables to the to graphql query as explained in the below article

https://www.kooijmanbart.com/add-graphql-variables-in-sitecore-jss

I have used this idea to pass the filter tag parameters as an additional variable.We can then pass this as a query string parameter when we invoke the JSS layout service.Below is a sample graphql query which accepts ItemSearchFieldQuery as a veritable and we we pass multiple filtering condition together.

query GetVideos( $videofilter: [ItemSearchFieldQuery]) {
search(rootItem: “/sitecore/content/Content Modules/Video Contents”, fieldsEqual: $videofilter) {
Results: results {
videos: items {
videoID: field(name: “videoid”)
thumbnailimage:item {
image: field(name: “thumbnailimage”) {
…ImageQuery
}
}
}
}
}
}fragment ImageQuery on ImageField {
src
}

The article was mentioned about sending only simple string as a variable. And passing a complex object like ItemSearchFieldQuery was not straight forward and hasn’t got much support from the community. After .peak on the sitecore dllss, I was getting stuck at the below error as my i was incorrectly passing the JSON structure that represent ItemSearchFieldQuery.

https://github.com/graphql-dotnet/graphql-dotnet/issues/816

As a resolution, to correctly format the response I was taken the below approach

  1. First taken parameter and convert that JSON to c# class using https://json2csharp.com/.

{
“videofilter”:[
{“name”: “IncludeInSearch”,”value”: “1” },
{“name”: “contenttags_sm”, “value”: “3bb5c65e7c8f4692886f4fc3e500ca18”},
{“name”: “contenttags_sm”, “value”: “78b1a8d30cca4c9bbb98446440d39d40”},
{“name”: “_templatename”, “value”: “Video”}
]
}

    public class Videofilter    {
        public string name { get; set; } 
        public string value { get; set; } 
    }

    public class Root    {
        public List<Videofilter> videofilter { get; set; } 
    }

2. Use the List in the Root class to to keep the filter tags send as query string in the layout service.

https://dev.local/sitecore/api/layout/render/jss?item=/&sc_apikey={596102D9-AF50-464A-AB69-A7EB04F19544}&videofilter=36bc9028dcd84153a2863224cfdfc0a2,3bb5c65e7c8f4692886f4fc3e500ca18,78b1a8d30cca4c9bbb98446440d39d40

3.Then use the below code snippet to create the Dictionary that represent ItemSearchFieldQuery variable.

          var tagArray = videofilter.Split(',');//videofilter=sending tags as query string in comma separated value.

                if (tagArray != null && tagArray.Length > 0)
                {
                    Root root = new Root() { fieldsEqual = new List<FieldsEqual>() };

                    root.fieldsEqual.Add(new FieldsEqual() { name = "IncludeInSearch", value = "1" });

                    root.fieldsEqual.Add(new FieldsEqual() { name = "_templatename", value = "Video" });
                                        
                    foreach (string tag in tagArray)
                    {
                        root.fieldsEqual.Add(new FieldsEqual() { name = "contenttags_sm", value = tag });
                    }

                    var json = JsonConvert.SerializeObject(root);

                    JObject jobject = JObject.Parse(json);

                    var variables = ToInputs(jobject);

                    localGraphQlRequest2.LocalVariables.Add(variableName, variables["fieldsEqual"]);

 public Inputs ToInputs(JObject obj)
        {
            var variables = obj?.GetValue() as Dictionary<string, object>
                            ?? new Dictionary<string, object>();
            return new Inputs(variables);
        }

Leave a comment