1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6083],{7400:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>y});var r=n(52411),s=n(16690),i=n(68946);n(14232);var o=n(17674);n(48230);var a=n(57272),l=n(81843),d=n(75381),h=n(54416),u=n(75369),p=d.P,c=function(e){return console.warn("Component Editor was not imported, exported, or provided by MDXProvider as global scope"),(0,o.yg)("div",e)},g={Layout:p,pageData:{title:"Custom Sorting",description:"Learn how to create custom sorting for user defined models",type:"docs",showPageHeader:!0,fullWidth:!1,version:"5.x"},docsearch:{type:"docs",weight:100,versions:["5.x"]},navigation:h,versions:u,tableOfContents:[{title:"Overview",slug:"overview",children:[]},{title:"Creating the New Sorter for the GraphQL Schema",slug:"creating-the-new-sorter-for-the-graph-ql-schema",children:[]},{title:"Creating the Sort Plugin to Handle New Custom Sorters",slug:"creating-the-sort-plugin-to-handle-new-custom-sorters",children:[{title:"DynamoDB Systems",slug:"dynamo-db-systems",children:[]},{title:"Elasticsearch Systems",slug:"elasticsearch-systems",children:[]}]},{title:"Conclusion",slug:"conclusion",children:[]}]};function y(e){var t=e.components,n=(0,i._)(e,["components"]);return(0,o.yg)("wrapper",(0,s._)((0,r._)({},g,n),{components:t,mdxType:"MDXLayout"}),(0,o.yg)(l.F,{type:"success",title:"What you'll learn",mdxType:"Alert"},(0,o.yg)("ul",null,(0,o.yg)("li",{parentName:"ul"},"how to create custom sort enums"),(0,o.yg)("li",{parentName:"ul"},"how to resolve custom sort in DynamoDB system"),(0,o.yg)("li",{parentName:"ul"},"how to resolve custom sort in DynamoDB+Elasticsearch system"))),(0,o.yg)(a.D,{level:2,id:"overview",nextElement:{type:"heading",depth:2}},"Overview"),(0,o.yg)(a.D,{level:2,id:"creating-the-new-sorter-for-the-graph-ql-schema",nextElement:{type:"paragraph"}},"Creating the New Sorter for the GraphQL Schema"),(0,o.yg)("p",null,"The first thing users need to do is to add a ",(0,o.yg)("inlineCode",{parentName:"p"},"CmsEntryFieldSortingPlugin"),":"),(0,o.yg)(c,{title:"apps/api/headlessCms/src/plugins/customSorterPlugin.ts",lang:"typescript",mdxType:"Editor"},'// there is a class and a function so users can use whatever suits their way of writing code\nimport {\n CmsGraphQLSchemaSorterPlugin,\n createCmsGraphQLSchemaSorterPlugin\n} from "@webiny/api-headless-cms";\n\nexport const customSorterPlugin = createCmsGraphQLSchemaSorterPlugin(({ sorters, model }) => {\n // we only want to add the sorter when generating a certain model GraphQL Schema\n if (model.modelId !== "yourTargetModelId") {\n return sorters;\n }\n return [...sorters, "myCustomSorting_ASC", "myCustomSorting_DESC"];\n});'),(0,o.yg)("p",null,"And then add the plugin into the plugins array of the ",(0,o.yg)("inlineCode",{parentName:"p"},"createHandler()"),":"),(0,o.yg)(c,{title:"apps/api/headlessCms/src/index.ts",lang:"typescript",mdxType:"Editor"},"const handler = createHandler({\n plugins: [\n // other plugins,\n customSorterPlugin\n ]\n});"),(0,o.yg)(a.D,{level:2,id:"creating-the-sort-plugin-to-handle-new-custom-sorters",nextElement:{type:"heading",depth:3}},"Creating the Sort Plugin to Handle New Custom Sorters"),(0,o.yg)(a.D,{level:3,id:"dynamo-db-systems",nextElement:{type:"paragraph"}},"DynamoDB Systems"),(0,o.yg)("p",null,"As the sorting in the DynamoDB systems is basic, letâs show the example on how to sort via a nested object value:"),(0,o.yg)(c,{title:"apps/api/headlessCms/src/plugins/yourCustomSortPlugin.ts",lang:"typescript",mdxType:"Editor"},'// there is a class and a function so users can use whatever suits their way of writing code\nimport {\n CmsEntryFieldSortingPlugin,\n createCmsEntryFieldSortingPlugin\n} from "@webiny/api-headless-cms-ddb";\n\nconst customSortingPlugin = createCmsEntryFieldSortingPlugin({\n canUse: ({ fieldId, model }) => {\n return model.modelId === "yourTargetModelId" && fieldId === "myCustomSorting";\n },\n createSort: ({ fields, order }) => {\n // let\'s find the field we want to sort by\n // you can find the field by joining all its parents fieldId + the fieldId you want to sort by via a dot (.)\n // this is the information user must know (possibly they can create a finder for the field)\n const fieldId = "nestedObject.anotherNestedObject.numberField"; // the fieldId is later on used in error report - if any\n const field = fields[fieldId];\n // we can create a field path via the built-in method\n const valuePath
1= field.createPath({\n field\n });\n // or manually\n // note that all entry values are stored in the values object - thats why it is in the beginning of the string\n const valuePath = `values.nestedObject.anotherNestedObject.numberField`;\n\n return {\n field,\n fieldId,\n valuePath,\n reverse: order === "DESC"\n };\n }\n});'),(0,o.yg)("p",null,"And then add the plugin into the plugins array of the ",(0,o.yg)("inlineCode",{parentName:"p"},"createHandler()"),":"),(0,o.yg)(c,{title:"apps/api/headlessCms/src/index.ts",lang:"typescript",mdxType:"Editor"},"const handler = createHandler({\n plugins: [\n // other plugins,\n customSortingPlugin\n ]\n});"),(0,o.yg)("p",null,"This plugin matches the ",(0,o.yg)("inlineCode",{parentName:"p"},"myCustomSorting")," value from ",(0,o.yg)("inlineCode",{parentName:"p"},"myCustomSorting_ASC")," and then it creates sort variables which are used in our built-in sorting, which uses ",(0,o.yg)("inlineCode",{parentName:"p"},"lodash.orderBy")," library.\nVariables are:"),(0,o.yg)("ul",null,(0,o.yg)("li",{parentName:"ul"},"field - check out the ",(0,o.yg)("a",{parentName:"li",href:"https://github.com/webiny/webiny-js/blob/59046097e7dc93bd9b256999a4056a31ceb0f2e9/packages/api-headless-cms-ddb/src/operations/entry/filtering/types.ts#L13"},"interface")),(0,o.yg)("li",{parentName:"ul"},"fieldId - full path to the field in the ",(0,o.yg)("inlineCode",{parentName:"li"},"fields")," object - it is used for error reporting if it happens"),(0,o.yg)("li",{parentName:"ul"},"valuePath - full path to the field in the database record - it is used to get the value by which we are going to sort"),(0,o.yg)("li",{parentName:"ul"},"reverse - in which order will the records go to the API response")),(0,o.yg)(l.F,{type:"warning",mdxType:"Alert"},(0,o.yg)("p",null,"Although we gave an example to sort by nested objects, please do not do that in production as it will get quite slow at some point.")),(0,o.yg)(a.D,{level:3,id:"elasticsearch-systems",nextElement:{type:"code",lang:"typescript",meta:"apps/api/headlessCms/src/plugins/yourCustomSortPlugin.ts"}},"Elasticsearch Systems"),(0,o.yg)(c,{title:"apps/api/headlessCms/src/plugins/yourCustomSortPlugin.ts",lang:"typescript",mdxType:"Editor"},'// there is a class and a function so users can use whatever suits their way of writing code\nimport {\n CmsEntryElasticsearchBodyModifierPlugin,\n createCmsEntryElasticsearchBodyModifierPlugin\n} from "@webiny/api-headless-cms-ddb-es";\n\nconst customBodyModifier = createCmsEntryElasticsearchBodyModifierPlugin({\n modelId: "yourTargetModelId",\n modifyBody: ({ model, body, where }) => {\n // as we filter the models by setting the modelId in the plugin configuration there is no need to do it again\n // we need to check if there is a custom sorting in the body\n // we always generate a object sorting, so if there is no myCustomSorting key - there is no custom sorting\n if (!body.sort.myCustomSorting) {\n return;\n }\n body.sort = {\n _script: {\n type: "number",\n script: {\n lang: "painless",\n inline: "some script"\n },\n order: "asc"\n }\n };\n }\n});'),(0,o.yg)("p",null,"And then add the plugin into the plugins array of the ",(0,o.yg)("inlineCode",{parentName:"p"},"createHandler()"),":"),(0,o.yg)(c,{title:"apps/api/headlessCms/src/index.ts",lang:"typescript",mdxType:"Editor"},"const handler = createHandler({\n plugins: [\n // other plugins,\n customBodyModifier\n ]\n});"),(0,o.yg)("p",null,"With this plugin, we replace the sort completely as it would fail. There is no ",(0,o.yg)("inlineCode",{parentName:"p"},"myCustomSorting")," field and the Elasticsearch query would fail when it would hit the server."),(0,o.yg)(l.F,{type:"info",mdxType:"Alert"},(0,o.yg)("p",null,"Note that we used the ",(0,o.yg)("inlineCode",{parentName:"p"},"CmsEntryElasticsearchBodyModifierPlugin")," in the example because we needed to replace whole ",(0,o.yg)("inlineCode",{parentName:"p"},"sort")," object on the ",(0,o.yg)("inlineCode",{parentName:"p"},"body"),". If you need to modify the sort (add or remove something), feel free to use the ",(0,o.yg)("inlineCode",{parentName:"p"},"CmsEntryElasticsearchSortModifierPlugin"),".")),(0,o.yg)(a.D,{level:2,id:"conclusion",nextElement:{type:"paragraph"}},"Conclusion"),(0,o.yg)("p",null,"While custom sorters are a powerful functionality, use them carefully as it might degrade the system performance - especially in the DynamoDB systems."))}y.isMDXComponent=!0,y.layoutProps=g}
1,54202:(e,t,n)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/5.x/headless-cms/extending/custom-sorting",function(){return n(7400)}])}},e=>{e.O(0,[3220,9730,9610,636,6593,8792],()=>e(e.s=54202)),_N_E=e.O()}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.