PageSourceSearch

https://docs.mia-platform.eu/assets/js/0b597d51.9fc168cf.js

js mia-platform.eu collected 2026-10-02 06:03:05 UTC 75,364 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkmia_platform_docs=self.webpackChunkmia_platform_docs||[]).push([["10665"],{560561(e,n,i){i.r(n),i.d(n,{metadata:()=>t,default:()=>h,frontMatter:()=>s,contentTitle:()=>a,toc:()=>r,assets:()=>c});var t=JSON.parse('{"id":"products/fast_data/configuration/config_maps/aggregation","title":"Aggregation Configuration","description":"The Aggregation configuration is used by the Single View Creator to generate a document with the same structure defined in the Single View data model and the content calculated by aggregating data inside the projections.","source":"@site/versioned_docs/version-15.0.1/products/fast_data/configuration/config_maps/aggregation.md","sourceDirName":"products/fast_data/configuration/config_maps","slug":"/products/fast_data/configuration/config_maps/aggregation","permalink":"/docs/15.0.1/products/fast_data/configuration/config_maps/aggregation","draft":false,"unlisted":false,"tags":[],"version":"15.0.1","frontMatter":{"id":"aggregation","title":"Aggregation Configuration","sidebar_label":"Aggregation"},"sidebar":"fastData","previous":{"title":"ER Schema","permalink":"/docs/15.0.1/products/fast_data/configuration/config_maps/erSchema"},"next":{"title":"Single View Key","permalink":"/docs/15.0.1/products/fast_data/configuration/config_maps/singleViewKey"}}'),o=i(474848),d=i(28453);let s={id:"aggregation",title:"Aggregation Configuration",sidebar_label:"Aggregation"},a,c={},r=[{value:"Manual configuration of aggregation",id:"manual-configuration-of-aggregation",level:2},{value:"Pipeline",id:"pipeline",level:3},{value:"Mapper",id:"mapper",level:3},{value:"Configuration with JSON file",id:"configuration-with-json-file",level:2},{value:"Dependencies",id:"dependencies",level:3},{value:"Mapping",id:"mapping",level:3},{value:"Join Dependency",id:"join-dependency",level:3},{value:"Advanced options",id:"advanced-options",level:3},{value:"Using the same Projection as a Dependency multiple times under different conditions",id:"using-the-same-projection-as-a-dependency-multiple-times-under-different-conditions",level:4},{value:"Referencing an aliased Projection inside a dependency",id:"referencing-an-aliased-projection-inside-a-dependency",level:4},{value:"Changing the query that finds the Projection based on their identifier",id:"changing-the-query-that-finds-the-projection-based-on-their-identifier",level:4},{value:"Using conditional expressions on dependencies definitions and mappings",id:"using-conditional-expressions-on-dependencies-definitions-and-mappings",level:4},{value:"<code>null</code> values inside conditional expressions",id:"null-values-inside-conditional-expressions",level:4},{value:"Set resolution order of dependencies",id:"set-resolution-order-of-dependencies",level:4},{value:"Aggregate documents with different <code>__STATE__</code> other than <code>PUBLIC</code>",id:"aggregate-documents-with-different-__state__-other-than-public",level:4},{value:"Use the No Code",id:"use-the-no-code",level:2},{value:"Selection of the Base Projection",id:"selection-of-the-base-projection",level:3},{value:"How to map fields",id:"how-to-map-fields",level:3},{value:"Automatic generation of dependencies via Path",id:"automatic-generation-of-dependencies-via-path",level:3},{value:"Manage the existing dependencies",id:"manage-the-existing-dependencies",level:3},{value:"Create a Join Dependency with the No Code",id:"create-a-join-dependency-with-the-no-code",level:3},{value:"Advanced Mode",id:"advanced-mode",level:3},{value:"Error and Warning management",id:"error-and-warning-management",level:3},{value:"Reset the Aggregation",id:"reset-the-aggregation",level:3}];function l(e){let n={a:"a",admonition:"admonition",br:"br",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,d.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["The Aggregation configuration is used by the ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/concepts/architecture#single-view-creator-svc",children:"Single View Creator"})," to generate a document with the same structure defined in the ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/configuration/single_views#single-view-data-model",children:"Single View data model"})," and the content calculated by aggregating data inside the projections."]}),"\n",(0,o.jsx)(n.p,{children:"The aggregation is mounted as a config map of the Single View Creator Service and might be composed by:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["a manual configuration, composed of ",(0,o.jsx)(n.code,{children:"pipeline.js"})," and ",(0,o.jsx)(n.code,{children:"mapper.js"})," files inside the ",(0,o.jsx)(n.em,{children:"configuration"})," config map (automatically created adding the ",(0,o.jsx)(n.code,{children:"Single View Creator"})," plugin from the Mia Marketplace)"]}),"\n",(0,o.jsxs)(n.li,{children:["a low-code configuration, composed of the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," file inside the ",(0,o.jsx)(n.em,{children:"aggregation"})," config map (automatically created adding the ",(0,o.jsx)(n.code,{children:"Single View Creator - Low Code"})," plugin from the Mia Marketplace)."]}),"\n"]}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsxs)(n.p,{children:["We strongly recommend to use the ",(0,o.jsx)(n.code,{children:"Single View Creator - Low Code"})," to simplify your experience building the aggregation configuration. We also have a a step-by-step ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/tutorials/low-code",children:"tutorial"})," that you can refer to."]})}),"\n",(0,o.jsx)(n.h2,{id:"manual-configuration-of-aggregation",children:"Manual configuration of aggregation"}),"\n",(0,o.jsxs)(n.p,{children:["We advice to use the manual aggregation for particular cases that might not be achieved with the ",(0,o.jsx)(n.code,{children:"Single View Creator - Low Code"})," which include a better support and takes care of performances and edge cases."]}),"\n",(0,o.jsxs)(n.p,{children:["But in case is needed to build the aggregation logic, you'll need two files: the ",(0,o.jsx)(n.code,{children:"pipeline.js"})," and the ",(0,o.jsx)(n.code,{children:"mapper.js"}),". The user can review and update these files from the ",(0,o.jsx)(n.em,{children:"Microservices"})," section, selecting the Single View Creator, in the ",(0,o.jsx)(n.em,{children:"ConfigMaps & Secrets"})," section."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["When selecting the ",(0,o.jsx)(n.code,{children:"Single View Creator"})," plugin from the Mia Marketplace, these two files will automatically be created and already included in the service Config Map with a default content which should be changed for having a functional service."]})}),"\n",(0,o.jsx)(n.h3,{id:"pipeline",children:"Pipeline"}),"\n",(0,o.jsx)(n.p,{children:"It takes as input a MongoDB instance and returns a function. This function takes as input the Projection change identifier and returns an array."}),"\n",(0,o.jsxs)(n.p,{children:["If it is empty, a delete operation will be executed on the Single View identified by the ",(0,o.jsx)(n.code,{children:"singleViewKeyGenerator"})," result.\nIf it is not empty, an upsert operation will be executed on the Single View identified by the ",(0,o.jsx)(n.code,{children:"singleViewKeyGenerator"})," result."]}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsx)(n.p,{children:"If the pipeline returns an array with more than one element, only the first element will be used for the upsert."})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",metastring:'title="pipeline.js"',children:"module.exports = (mongoDb) => {\n  return async(logger, projectionChangeIdentifier) => {\n\n    const uniqueId = projectionChangeIdentifier.UNIQUE_ID\n    const MY_PROJECTION = 'projection-name'\n\n    // retrieve data from all projections you need for your single view\n    const projectionCollection = mongoDb.collection(MY_PROJECTION)\n    const projectionDataById = await projectionCollection.findOne({\n        UNIQUE_ID: uniqueId,\n        __STATE__: 'PUBLIC'\n    })\n\n    if (!projectionDataById) {\n      // it's expected to be a delete\n      logger.debug({ UNIQUE_ID: uniqueId }, 'single view public data not found')\n      return []\n    }\n    const singleViewData = projectionDataById\n    logger.debug({ singleViewData }, 'single view retrieved data')\n\n    return [\n      singleViewData,\n    ]\n  }\n}\n"})}),"\n",(0,o.jsx)(n.h3,{id:"mapper",children:"Mapper"}),"\n",(0,o.jsx)(n.p,{children:"It is a function that takes as argument the first element (if defined) of the result of the pipeline, and returns an object c
1ontaining the value updated for the Single View. The object returned should match the schema of the Single View."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",metastring:'title="mapper.js"',children:"module.exports = (logger, singleViewData) => {\n  const { UNIQUE_ID, NAME } = singleViewData\n\n  return {\n    myId: UNIQUE_ID,\n    name: NAME,\n  }\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Renaming and repositioning of the fields can be applied inside the mapper."}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsx)(n.p,{children:"We suggest implementing all the aggregation logic that can be reused for all the clients that will read the Single Views inside the mapper, they should be as generic as possible.\nIt is a good practice to have some calculation and aggregation logic inside the Single View Creator as far as it is reusable.\nIf you have to apply some custom logic try to do it inside an API Adapter specific for the client."})}),"\n",(0,o.jsx)(n.h2,{id:"configuration-with-json-file",children:"Configuration with JSON file"}),"\n",(0,o.jsx)(n.p,{children:"An example of a minimal configuration is as follows:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n  "version": "1.0.0",\n  "config": {\n    "SV_CONFIG": {\n      "dependencies": {\n        "DOCUMENT_NAME": {\n          "type": "projection",\n          "on": "_identifier"\n        }\n      },\n      "mapping": {\n        "newField": "DOCUMENT_NAME.field"\n      }\n    }\n  }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"SV_CONFIG"})," field is mandatory, as it is the starting point of the configuration of the Single View. It includes the needed information to map fields of the Single View (included the ",(0,o.jsx)(n.code,{children:"mapping"})," object) and which ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/configuration/projections",children:"projections"})," will be used to retrieve those values (included the ",(0,o.jsx)(n.code,{children:"dependencies"})," object)."]}),"\n",(0,o.jsx)(n.h3,{id:"dependencies",children:"Dependencies"}),"\n",(0,o.jsx)(n.p,{children:"Dependencies have two properties:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"type"}),": either ",(0,o.jsx)(n.code,{children:"projection"})," or ",(0,o.jsx)(n.code,{children:"config"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"on"}),": either ",(0,o.jsx)(n.code,{children:"_identifier"})," or some condition defined in the ER Schema."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["If the dependency is of type ",(0,o.jsx)(n.code,{children:"projection"})," and the ",(0,o.jsx)(n.code,{children:"on"})," field is set to ",(0,o.jsx)(n.code,{children:"_identifier"}),", then the data will be retrieved from the document with the matching identifier.\nIf the ",(0,o.jsx)(n.code,{children:"on"})," property of a ",(0,o.jsx)(n.code,{children:"projection"})," dependency is set to another string, then it is checked against the condition in the ER Schema that has the same name."]}),"\n",(0,o.jsxs)(n.p,{children:["If the dependency is of type ",(0,o.jsx)(n.code,{children:"config"})," it will not have an ",(0,o.jsx)(n.code,{children:"on"})," field, and instead the whole configuration will be defined in the JSON file, using the same structure as the one in ",(0,o.jsx)(n.code,{children:"SV_CONFIG"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"mapping",children:"Mapping"}),"\n",(0,o.jsx)(n.p,{children:"Each entry in the mapping has the following syntax:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'"singleViewFieldName": "value"\n'})}),"\n",(0,o.jsx)(n.p,{children:"Where value can be one of:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"projection field"}),": when it is a field taken from a Projection listed in the dependency, expressed with dot notation ",(0,o.jsx)(n.code,{children:'"newField": "DOCUMENT_NAME.field"'})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"configuration"}
1),": when a field is an object corresponding to a resolved config dependency, expressed with the dependency name ",(0,o.jsx)(n.code,{children:'"newField": "CONFIG_NAME"'})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"constant"}),": when using the constant syntax already seen in the ER diagram, e.g. ",(0,o.jsx)(n.code,{children:"__string__[hello]"}),", ",(0,o.jsx)(n.code,{children:"__integer__[42]"}),", ",(0,o.jsx)(n.code,{children:"__boolean__[true]"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"function result"}),": when using a custom function to compute the value of the Single View field, expressed with this syntax: ",(0,o.jsx)(n.code,{children:'"fromFileField": "__fromFile__[fileName]"'})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"For functions, the specified file must be added in a config map with the correct name, and must contain a default exported function, which will be used to compute the value of the field."}),"\n",(0,o.jsx)(n.p,{children:"The following parameters will be passed to each function:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"logger"}),": the logger instance used by the service,"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"clientMongo"}),": the instance of MongoDB used by the service,"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"dependenciesMap"}),": a map containing all the dependencies already loaded in the service memory."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Let's see an example of custom function."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:"async function myOwnCustomLogic (value) {\n  // some custom logic\n}\n\nmodule.exports = async function(logger, clientMongo, dependenciesMap) {\n\n    // access the order already got from the dependenciesMap\n    const order = dependenciesMap.get(\"pr_orders\")\n    \n    const fiscalCode = await clientMongo.collection('users').findOne({userId: order.id}).fiscalCode\n    const result = await myOwnCustomLogic(fiscalCode)\n    return {\n      surname: result.surname,\n      code: result.code\n    }\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"dependenciesMap"})," offers a ",(0,o.jsx)(n.code,{children:"get"})," method to access the dependencies already solved using the name of the dependency itself."]}),"\n",(0,o.jsx)(n.p,{children:"If the dependency you require is a Projection, the value returned will be the document of the Projection, otherwise if it's a config it will be the array of document resulting from the configuration."}),"\n",(0,o.jsx)(n.p,{children:"If the dependencies has not been resolved, for example due to a reference which failed because of a missing document, the value will be falsy in case of Projections and an empty array in case of config."}),"\n",(0,o.jsx)(n.admonition,{type:"warning",children:(0,o.jsxs)(n.p,{children:["You are supposed to access the ",(0,o.jsx)(n.code,{children:"dependenciesMap"})," ",(0,o.jsx)(n.strong,{children:"only"})," in read-only mode.\nWrite access to the ",(0,o.jsx)(n.code,{children:"dependenciesMap"})," are ",(0,o.jsx)(n.strong,{children:"not"})," officially supported and could be removed at any time."]})}),"\n",(0,o.jsx)(n.h3,{id:"join-dependency",children:"Join Dependency"}),"\n",(0,o.jsxs)(n.p,{children:["When you want to map a Single View field to an array of values, as it usually happens in 1",":N"," relations, you can use a config dependency with a ",(0,o.jsx)(n.code,{children:"joinDependency"})," field. This means that when the config will be calculated, the ",(0,o.jsx)(n.code,{children:"joinDependency"})," will be computed first, retrieving a list of all matching documents, then for each of those elements the configuration mapping will be applied, resulting in an array of elements, each having the same layout as the one specified in the config mapping."]}),"\n",(0,o.jsx)(n.h3,{id:"advanced-options",children:"Advanced options"}),"\n",(0,o.jsx)(n.h4,{id:"using-the-same-projection-as-a-dependency-multiple-times-under-different-conditions",children:"Using the same Projection as a Dependency multiple times under different c
1onditions"}),"\n",(0,o.jsx)(n.p,{children:"When listing dependencies, it is mandatory that each dependency has a different name, as its name is used to identify it. When it comes to config, this is not a problem, as you can name a config dependency as you wish, but it is different when we need to deal with Projections."}),"\n",(0,o.jsx)(n.p,{children:"For example, how would we describe a Single View of users that need to have their partner as a field? For this case we must have two references:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["a reference to the ",(0,o.jsx)(n.strong,{children:"users"})," that is based on their identifier to get the core of the Single View"]}),"\n",(0,o.jsxs)(n.li,{children:["a reference to a ",(0,o.jsx)(n.strong,{children:"user"}),", that is based on some condition linked to the marriage"]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"For this example, we will consider the following ER Schema"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version":"1.0.0",\n   "config":{\n      "PEOPLE":{\n         "outgoing":{\n            "MARRIAGE":{\n               "conditions":{\n                  "PEOPLE_TO_MARRIAGE":{\n                     "condition":{\n                        "a":"id"\n                     }\n                  }\n               }\n            }\n         }\n      },\n      "MARRIAGE":{\n         "outgoing":{\n            "PEOPLE":{\n               "conditions":{\n                  "MARRIAGE_a_TO_PEOPLE":{\n                     "condition":{\n                        "id":"a"\n                     }\n                  },\n                  "MARRIAGE_b_TO_PEOPLE":{\n                     "condition":{\n                        "id":"b"\n                     }\n                  }\n               }\n            }\n         }\n      }\n   }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["If we tried to solve the problem without advanced options, we would write a ",(0,o.jsx)(n.strong,{children:"wrong"})," configuration like the following:"]}),"\n",(0,o.jsx)(n.admonition,{type:"warning",children:(0,o.jsx)(n.p,{children:"The configuration below is incorrect, and presented only to clearly show the need and flexibility of aliases. Do not use this kind of configuration."})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version":"1.1.0",\n   "config":{\n      "SV_CONFIG":{\n         "dependencies":{\n            "PEOPLE":{\n               "type":"projection",\n               "on":"_identifier"\n            },\n            "MARRIAGE":{\n               "type":"projection",\n               "on":"PEOPLE_TO_MARRIAGE"\n            },\n            "PEOPLE":{\n               "type":"projection",\n               "on":"MARRIAGE_b_TO_PEOPLE"\n            }\n         },\n         "mapping":{\n            "name":"PEOPLE.name",\n            "marriedWith":"PEOPLE.name"\n         }\n      }\n   }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["This is incorrect, because there is ambiguity about which ",(0,o.jsx)(n.code,{children:"PEOPLE"})," dependency to use in the mapping."]}),"\n",(0,o.jsxs)(n.p,{children:["You can solve this problem using the ",(0,o.jsx)(n.code,{children:"aliasOf"})," option, which allows to use a different name for a dependency of type ",(0,o.jsx)(n.code,{children:"projection"}),". When using ",(0,o.jsx)(n.code,{children:"aliasOf: 'PROJECTION_NAME'"}),", the named dependency is linked to that Projection."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"aliasOf"})," field is supported from the version ",(0,o.jsx)(n.code,{children:"1.1.0"})," of the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," which is supported from the version ",(0,o.jsx)(n.code,{children:"3.6.0"})," of the Single View Creator service"]})}),"\n",(0,o.jsxs)(n.p,{children:["Now that the ",(0,o.jsx)(n.code,{children:"aliasOf"})," option is clear, we can have a look at the following configuration, which solves the problem in the example:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version":"1.1.0",\n   "config":{\n      "SV_CONFIG":{\n         "dependencies":{\n            "PEOPLE":{\n               "type":"projection",\n               "on":"_identifier"\n            },\n            "MARRIAGE":{\n               "type":"projection",\n               "on":"PEOPLE_TO_MARRIAGE"\n            },\n            "PARTNER":{\n               "type":"projection",\n               "aliasOf":"PEOPLE",\n               "on":"MARRIAGE_b_TO_PEOPLE"\n            }\n         },\n         "mapping":{\n            "name":"PEOPLE.name",\n            "marriedWith":"PARTNER.name"\n         }\n      }\n   }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["As you can see, we used the same Projection t
1wice, under different conditions: the first time we matched the record based on its identifier (",(0,o.jsx)(n.code,{children:"PEOPLE"})," dependency, without alias), the second time we matched the record based on the ",(0,o.jsx)(n.code,{children:"MARRIAGE_b_TO_PEOPLE"})," condition (",(0,o.jsx)(n.code,{children:"PARTNER"})," dependency, with alias)."]}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"aliasOf"})," can also be used to rename long Projection names without the need of them being re-used. Instead of using ",(0,o.jsx)(n.code,{children:"company_department_prefix_people_table.name"})," we can alias the Projection to ",(0,o.jsx)(n.code,{children:"people"})," and use ",(0,o.jsx)(n.code,{children:"people.name"})," in the mapping!"]})}),"\n",(0,o.jsxs)(n.p,{children:["Now let's imagine we need a ",(0,o.jsx)(n.code,{children:"oneToMany"})," relationship, say, a ",(0,o.jsx)(n.code,{children:"PEOPLE"})," to ",(0,o.jsx)(n.code,{children:"CHILDREN"})," relationship. For that there's two things we need to consider. Let's see an example:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version": "1.3.0",\n   "config": {\n      "SV_CONFIG": {\n         "dependencies": {\n            "PEOPLE": {\n               "type": "projection",\n               "on": "_identifier",\n            },\n            "CHILDREN_CONFIG": {\n               "type": "config",\n            },\n         },\n         "mapping": {\n            "name":"PEOPLE.name",\n            "children": "CHILDREN_CONFIG",\n         },\n      },\n      "CHILDREN_CONFIG": {\n         "joinDependency": "CHILDREN",\n         "dependencies": {\n            "CHILDREN": {\n               "type": "projection",\n               "on": "PEOPLE_TO_CHILDREN",\n               "aliasOf": "PEOPLE",\n            },\n         },\n         "mapping": {\n            "name": "CHILDREN.name",\n         },\n      },\n   },\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The first thing is that the ",(0,o.jsx)(n.code,{children:"aliasOf"})," property always goes inside the ",(0,o.jsx)(n.code,{children:"type: projection"})," configuration, as you can see we defined it in the ",(0,o.jsx)(n.code,{children:"CHILDREN.dependencies.children"})," object instead of the ",(0,o.jsx)(n.code,{children:"SV_CONFIG.dependencies.CHILDREN"})," object. The second is that we don't use ",(0,o.jsx)(n.code,{children:"people"})," as a ",(0,o.jsx)(n.code,{children:"joinDependency"}),", but we use the below aliased ",(0,o.jsx)(n.code,{children:"children"})," instead."]}),"\n",(0,o.jsx)(n.h4,{id:"referencing-an-aliased-projection-inside-a-dependency",children:"Referencing an aliased Projection inside a dependency"}),"\n",(0,o.jsxs)(n.p,{children:["You can reference a dependency under alias also in another dependency, with the ",(0,o.jsx)(n.code,{children:"useAlias"})," option. Since ",(0,o.jsx)(n.code,{children:"CHILD_TO_MOTHER"})," refers to the ER-Schema, which uses only the Projections name and not the dependencies name, you need to use ",(0,o.jsx)(n.code,{children:"useAlias"})," to specify which is the specific dependency that refers to the Projection of the relation you want to use."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"useAlias"})," field is supported from version ",(0,o.jsx)(n.code,{children:"1.1.0"})," of the ",(0,o.jsx)(n.code,{children:"aggregation.json"}),", which is supported from the version ",(0,o.jsx)(n.code,{children:"3.6.0"})," of the Single View Creator service"]})}),"\n",(0,o.jsxs)(n.p,{children:["If we needed to use the ",(0,o.jsx)(n.code,{children:"PARTNER"})," dependency as a base for another dependency (for example, if we are looking for the mother in law), a valid configuration would be:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'...\n"PARTNER":{\n  "type":"projection",\n  "aliasOf":"PEOPLE",\n  "on":"MARRIAGE_b_TO_PEOPLE"\n},\n"MOTHER_IN_LAW":{\n  "type":"projection",\n  "useAlias":"PARTNER",\n  "on":"CHILD_TO_MOTHER",\n  "aliasOf":"PEOPLE"\n}\n...\n'})}),"\n",(0,o.jsxs)(n.p,{children:["Note that we used ",(0,o.jsx)(n.code,{children:"aliasOf"})," inside the ",(0,o.jsx)(n.code,{children:"MOTHER_IN_LAW"})," dependency as well because we wanted to keep on using the same base Projection, but it is not mandatory, as long as you are using another Projection that is not declared elsewhere in the dependencies."]}),"\n",(0,o.jsx)(n.h4,{id:"changing-the-query-that-finds-the-projection-based-on-their-identifier",children:"Changing the query that finds the Projection based on their identifier"}),"\n",(0,o.jsxs)(n.p,{children:["Sometimes, when writing a dependency of a Projection that is matched on its ",(0,o.jsx)(n.code,{children:"_identifier"}),", we find that the identifier has more fields than we want, or has fields with different names, which makes the automatic query mapping result in no documents found.\nIn this scenario, you can employ the ",(0,o.jsx)(n.code,{children:"identifierQueryMapping"})," option, which provides a new query mapping for the identifier of a Projection, allowing you to have a custom way of matching documents based on their identifier."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"identifierQueryMapping"})," field is supported from the version ",(0,o.jsx)(n.code,{children:"1.1.0"})," of the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," which is supported from the version ",(0,o.jsx)(n.code,{children:"3.6.0"})," of the Single View Creator service"]})}),"\n",(0,o.jsx)(n.p,{children:"In particular, there are two main cases when this could come in handy:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsx)(n.li,{children:"renaming fields for querying"}),"\n",(0,o.jsx)(n.li,{children:"reducing the number of fields to query on"}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Renaming fields can be required when you want to achieve a high level of decoupling, so you avoid using the document identifier key, but instead you use a more explicit name, for example instead of ",(0,o.jsx)(n.code,{children:'"id"'})," you might want to use ",(0,o.jsx)(n.code,{children:'"my_single_view_id"'}),", because this clearly shows what this ",(0,o.jsx)(n.code,{children:'"id"'})," refers to.\nAn identifier with that logic would be:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n  "my_single_view_id": "12345"\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["This would not match a document without a field named ",(0,o.jsx)(n.code,{children:"my_single_view_id"}),". In that case, you could map that in the aggregation config in the following way:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'...\n"PROJECTION_NAME": {\n  "on": "_identifier",\n  "identifierQueryMapping": {\n    "id": "_identifier.my_single_view_id"\n  }\n}\n...\n'})}),"\n",(0,o.jsx)(n.p,{children:"Reducing the number of fields to query on will help you if you have a custom function for the generation of Projections changes, which includes additional fields. For example, if you need to generate a Single View in a different way based on a flag in the identifier. An identifier could have a value like the following:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n  "the_id": "12345",\n  "special": "true"\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:'"special"'})," field is not part of the single document we want to find, but it is used elsewhere in the Single View creation. To avoid having queries that do not find any element, we can map the identifier like that:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'...\n"PROJECTION_NAME": {\n  "on": "_identifier",\n  "identifierQueryMapping": {\n    "the_id": "_identifier.the_id"\n  }\n}\n...\n'})}),"\n",(0,o.jsx)(n.admonition,{type:"caution",children:(0,o.jsxs)(n.p,{children:["Remember that for ",(0,o.jsx)(n.code,{children:"identifierQueryMapping"})," to be used, you still need to explicitly set the ",(0,o.jsx)(n.code,{children:"on"})," field of the dependency to ",(0,o.jsx)(n.code,{children:"_identifier"}),", otherwise it will not be considered valid."]})}),"\n",(0,o.jsx)(n.h4,{id:"using-conditional-expressions-on-dependencies-definitions-and-mappings",children:"Using conditional expressions on dependencies definitions and mappings"}),"\n",(0,o.jsx)(n.admonition,{type:"caution",children:(0,o.jsxs)(n.p,{children:["Starting with the release of Console ",(0,o.jsx)(n.code,{children:"v13.0.0"}),", the usage of this advanced feature (",(0,o.jsx)(n.code,{children:"_select"}),") is ",(0,o.jsx)(n.strong,{children:"deprecated"}),", as it will be replaced\nin the future with a better solution for pre-filtering which projections should be included in the aggregation."]})}),"\n",(0,o.jsx)(n.p,{children:"Dependencies are a way to gather data that will be used in the mapping section, creating the Single View, and as Single Views grow in complexity, you might need to use conditional expressions to use different dependencies configurations and/or change the mapped output of a Single View."}),"\n",(0,o.jsx)(n.p,{children:"If you have not had this necessity yet, this might be somewhat abstract, so we will directly dive into an example."}),"\n",(0,o.jsxs)(n.p,{children:["We have a System of Record that consists of multiple Projections about jobs, one for each different job. For example, we have ",(0,o.jsx)(n.code,{children:"DOCTOR"})," and ",(0,o.jsx)(n.code,{children:"FIREFIGHTER"}),". If you want to create a ",(0,o.jsx)(n.code,{children:"USER"})," Single View which has the information coming from its job Projection, you need a way to get a dependency which is either a ",(0,o.jsx)(n.code,{children:"DOCTOR"})," or a ",(0,o.jsx)(n.code,{children:"FIREFIGHTER"}),".\nA naive solution could be just putting both Projections as dependencies and using both of them in the mapping. This would cause the Single View to have tw
1o different ",(0,o.jsx)(n.code,{children:"firefighter"})," and ",(0,o.jsx)(n.code,{children:"doctor"})," fields, one of them undefined, which is clearly not ideal."]}),"\n",(0,o.jsxs)(n.p,{children:["Thanks to the ",(0,o.jsx)(n.code,{children:"_select"})," option, we can create a ",(0,o.jsx)(n.code,{children:"JOB"})," dependency, which will use the ",(0,o.jsx)(n.code,{children:"DOCTOR"})," ",(0,o.jsx)(n.em,{children:"or"})," ",(0,o.jsx)(n.code,{children:"FIREFIGHTER"})," Projection based on the value of another field, as shown below:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version":"1.1.0",\n   "config":{\n      "SV_CONFIG":{\n         "dependencies":{\n            "USER":{\n               "type":"projection",\n               "on":"_identifier"\n            },\n            "JOB_DESCRIPTION":{\n               "type":"projection",\n               "_select":{\n                  "options":[\n                     {\n                        "when":{\n                           "==":[\n                              "USER.job",\n                              "__string__[doctor]"\n                           ]\n                        },\n                        "value":{\n                           "aliasOf":"DOCTOR",\n                           "on":"USER_to_DOCTOR"\n                        }\n                     },\n                     {\n                        "when":{\n                           "==":[\n                              "USER.job",\n                              "__string__[firefighter]"\n                           ]\n                        },\n                        "value":{\n                           "aliasOf":"FIREFIGHTER",\n                           "on":"User_to_FIREFIGHTER"\n                        }\n                     }\n                  ],\n                  "default":{\n                     "aliasOf":"DOCTOR",\n                     "on":"USER_to_DOCTOR"\n                  }\n               }\n            }\n         },\n         "mapping":{\n            "name":"USER.name",\n            "job":{\n               "type":"JOB_DESCRIPTION.type",\n               "role":"JOB_DESCRIPTION.role"\n            }\n         }\n      }\n   }\n}\n'})}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"_select_"})," field is supported from the version ",(0,o.jsx)(n.code,{children:"1.1.0"})," of ",(0,o.jsx)(n.code,{children:"aggregation.json"})," which is supported from version ",(0,o.jsx)(n.code,{children:"3.6.0"})," of the Single View Creator service"]})}),"\n",(0,o.jsxs)(n.p,{children:["As you can see, the ",(0,o.jsx)(n.code,{children:"_select"})," option has a long set of rules, which we are going to break down here."]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"_select"})," is a way of providing one of many different configurations for a specific dependency, based on some conditions.\nEach possible configuration is an object in the ",(0,o.jsx)(n.code,{children:"options"})," array. If none of the ",(0,o.jsx)(n.code,{children:"options"})," has a matching condition, the value in the ",(0,o.jsx)(n.code,{children:"default"})," field is used.\nEach option has two fields:"]}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"when"}),": the condition that must be matched in order to use the ",(0,o.jsx)(n.code,{children:"value"}),";"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"value"}),": the configuration that will be used for this dependency if the ",(0,o.jsx)(n.code,{children:"when"})," condition is met."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"when"})," field is an object with an operator (available operators: ",(0,o.jsx)(n.code,{children:"=="}),", ",(0,o.jsx)(n.code,{children:"!="}),", ",(0,o.jsx)(n.code,{children:">"}),", ",(0,o.jsx)(n.code,{children:"<"}),", ",(0,o.jsx)(n.code,{children:">="}),", ",(0,o.jsx)(n.code,{children:"<="}),") as a field key, and its relative field value is an array of operands.\nFor example, using the equality operator, we can write this condition:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'"when":{\n  "==":[\n    "USER.job",\n    "__string__[firefighter]"\n  ]\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["Here, the first operand is a variable which takes its value from ",(0,o.jsx)(n.code,{children:"USER.job"}),", while the second operand is a constant string: ",(0,o.jsx)(n.code,{children:'"doctor"'}),". This simply means that this condition will match when the ",(0,o.jsx)(n.code,{children:"job"})," field of the ",(0,o.jsx)(n.code,{children:"USER"})," dependency is equal to ",(0,o.jsx)(n.code,{children:'"doctor"'}),".\nThis pattern is repeated for all other operators, as they are binary as well."]}),"\n",(0,o.jsxs)(n.p,{children:["As operand, it is possible to use constant values, in the exact same way as seen in the ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/configuration/config_maps/erSchema#syntax",children:"ER schema"}),"."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["Functions can also be used as value from version ",(0,o.jsx)(n.code,{children:"1.3.0"})," of the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," which is supported from version ",(0,o.jsx)(n.code,{children:"5.
11.0"})," of the Single View Creator service"]})}),"\n",(0,o.jsx)(n.p,{children:"The function works in the same way as explained in the Mapping section, with the only difference that it will accept only two parameters:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"logger"}),": the logger instance used by the service,"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"clientMongo"}),": the instance of mongoDB used by the service"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",metastring:'title="myFunc.js"',children:"module.exports = async function(logger, clientMongo) {\n   // Your code goes here\n}\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version": "1.3.0",\n   "config": {\n      ...\n      "when":{\n        "==":[\n          "USER.job",\n          "__fromFile__[myFunc]"\n        ]\n      }\n   }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"value"})," field is an object with exactly the same structure as a regular dependency, as it will be used as a dependency after the condition is met."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.strong,{children:"mappings"}),", the process of taking advantage of ",(0,o.jsx)(n.code,{children:"_select"})," is very similar: each field in the mapping can be expressed as an object with a ",(0,o.jsx)(n.code,{children:"_select"})," field that follows the same rules. Just keep in mind that the ",(0,o.jsx)(n.code,{children:"value"})," here is not a dependency (with fields such as ",(0,o.jsx)(n.code,{children:"type"})," and ",(0,o.jsx)(n.code,{children:"on"}),"), but a field of a dependency (e.g. ",(0,o.jsx)(n.code,{children:"MY_DEPENDENCY.field_name"}),")."]}),"\n",(0,o.jsx)(n.admonition,{type:"caution",children:(0,o.jsxs)(n.p,{children:["Starting with the release of Console ",(0,o.jsx)(n.code,{children:"v13.0.0"}),", the usage of this advanced feature (",(0,o.jsx)(n.code,{children:"_select"}),") is ",(0,o.jsx)(n.strong,{children:"deprecated"}),", as it will be replaced\nin the future with a better solution for pre-filtering which projections should be included in the aggregation."]})}),"\n",(0,o.jsxs)(n.h4,{id:"null-values-inside-conditional-expressions",children:[(0,o.jsx)(n.code,{children:"null"})," values inside conditional expressions"]}),"\n",(0,o.jsxs)(n.p,{children:["From version ",(0,o.jsx)(n.code,{children:"3.10.0"})," of the Single View Creator, logic expressions now accept ",(0,o.jsx)(n.code,{children:"null"})," as a value:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'...\n"withNull": {\n  "_select": {\n    "options": [\n      {\n        "when": {\n          "==": [\n            "JOB.age",\n            null\n          ]\n        },\n        "value": "__string__[unknown]"\n      }\n    ],\n    "default": "__string__[foobar]"\n  }\n}\n...\n'})}),"\n",(0,o.jsx)(n.h4,{id:"set-resolution-order-of-dependencies",children:"Set resolution order of dependencies"}),"\n",(0,o.jsxs)(n.p,{children:["From version ",(0,o.jsx)(n.code,{children:"4.1.0"})," of the Single-View-Creator, the resolution order of dependencies can be set with the field ",(0,o.jsx)(n.code,{children:"dependencyOrder"})," inside the aggregation file:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n  "version": "1.1.0",\n  "config": {\n    "SV_CONFIG": {\n      "dependencies": {\n        "PEOPLE": {\n          "type": "projection",\n          "on": "_identifier"\n        },\n        "PARTNER": {\n          "type": "projection",\n          "aliasOf": "PEOPLE",\n          "on": "MARRIAGE_TO_PEOPLE"\n        },\n        "MARRIAGE": {\n          "type": "projection",\n          "on": "PEOPLE_TO_MARRIAGE"\n        },\n        "CHILDREN_CONF": {\n          "type": "config"\n        }\n      },\n      "dependencyOrder": ["PEOPLE", "MARRIAGE", "PARTNER", "CHILDREN_CONF"],\n      "mapping": {\n        "name": "PEOPLE.name",\n        "marriedWith": "PARTNER.name",\n        "children": "CHILDREN_CONF"\n      }\n    }\n  },\n  "CHILDREN_CONF": {\n    ...\n  }\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"The aggregation above will be performed in the following order:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["Find the Projection in the ",(0,o.jsx)(n.code,{children:"PEOPLE"})," collection on MongoDB using ",(0,o.jsx)(n.code,{children:"identifier"})," got from the Projection Change as query."]}),"\n",(0,o.jsxs)(n.li,{children:["Find the Projection in the ",(0,o.jsx)(n.code,{children:"MARRIAGE"})," collection on MongoDB using the condition defined in the ER Schema as ",(0,o.jsx)(n.code,{children:"PEOPLE_TO_MARRIAGE"})]}),"\n",(0,o.jsxs)(n.li,{children:["Find the Projection in the ",(0,o.jsx)(n.code,{children:"PEOPLE"})," (which is the collection to be used in the dependency ",(0,o.jsx)(n.code,{children:"PARTNER"}),") using the condition defined in the ER Schema as ",(0,o.jsx)(n.code,{children:"MARRIAGE_TO_PEOPLE"})]}),"\n",(0,o.jsxs)(n.li,{children:["Calculate the aggregation defined in the ",(0,o.jsx)(n.code,{children:"CHILDREN_CONF"})," config"]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.em,{children:"Why should I care about the order resolution of the dependencies?"})}),"\n",(0,o.jsx)(n.p,{children:"The order resolution is important for the correctness of the aggregation since each step of the aggregation may use documents of the previous steps. Hence, if the order of the dependencies resolution is not correct, the Single View resulting from the aggregation will probably be wrong."}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsxs)(n.p,{children:["Since version ",(0,o.jsx)(n.code,{children:"v5.0.0"})," of Single View Creator service returning a Single View with the field ",(0,o.jsx)(n.code,{children:"__STATE__"})," from the aggregation will update the Single View to that state (among the other changes).",(0,o.jsx)(n.br,{}),"\n","This means, for instance, that if you set the ",(0,o.jsx)(n.code,{children:"__STATE__"})," to ",(0,o.jsx)(n.code,{children:"DRAFT"})," in the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," the Single View updated will have the ",(0,o.jsx)(n.code,{children:"__STATE__"})," equals to ",(0,o.jsx)(n.code,{children:"DRAFT"}),".\nPreviously, the ",(0,o.jsx)(n.code,{children:"__STATE__"})," you returned was ignored, and the Single View would always have the ",(0,o.jsx)(n.code,{children:"__STATE__"})," equals to ",(0,o.jsx)(n.code,{children:"PUBLIC"}),"."]})}),"\n",(0,o.jsxs)(n.h4,{id:"aggregate-documents-with-different-__state__-other-than-public",children:["Aggregate documents with different ",(0,o.jsx)(n.code,{children:"__STATE__"})," other than ",(0,o.jsx)(n.code,{children:"PUBLIC"})]}),"\n",(0,o.jsxs)(n.p,{children:["With version ",(0,o.jsx)(n.code,{children:"5.
11.0"})," of the Single View Creator the ",(0,o.jsx)(n.code,{children:"__STATE__"})," field in the Projection is taken into consideration when aggregating, meaning that if a dependency has its ",(0,o.jsx)(n.code,{children:"__STATE__"})," set to ",(0,o.jsx)(n.strong,{children:"anything else but"})," ",(0,o.jsx)(n.code,{children:"PUBLIC"})," it won't be added to the Single View."]}),"\n",(0,o.jsxs)(n.p,{children:["In case you would like to include other states too in the aggregation process you can do it with the ",(0,o.jsx)(n.code,{children:"onStates"})," field which allows you to define exactly which states you want to include to the Single View. The value is an array with any of the following states: ",(0,o.jsx)(n.code,{children:"PUBLIC"}),", ",(0,o.jsx)(n.code,{children:"DRAFT"}),", ",(0,o.jsx)(n.code,{children:"TRASH"}),", ",(0,o.jsx)(n.code,{children:"DELETED"}),"."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"onStates"})," field can be used from the version ",(0,o.jsx)(n.code,{children:"1.2.0"})," of the ",(0,o.jsx)(n.code,{children:"aggregation.json"})]})}),"\n",(0,o.jsx)(n.p,{children:"Here's a working example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{\n   "version": "1.2.0",\n   "config": {\n      "SV_CONFIG": {\n         "dependencies": {\n         "USER": {\n            "type": "projection",\n            "on": "_identifier",\n            "onStates": ["PUBLIC", "DRAFT"]\n         },\n         "WORK": {\n            "type": "projection",\n            "aliasOf": "JOB",\n            "on": "USER_TO_JOB",\n            "onStates": ["PUBLIC", "DRAFT"]\n         }\n         },\n         "mapping": {\n            "myId": "USER.id",\n            "job": "WORK.label"\n         }\n      }\n   }\n}\n'})}),"\n",(0,o.jsx)(n.h2,{id:"use-the-no-code",children:"Use the No Code"}),"\n",(0,o.jsxs)(n.p,{children:["From version ",(0,o.jsx)(n.code,{children:"11.3.0"})," of the Console, your project might have enabled the possibility to configure ER Schemas with the No Code feature. The new feature will be accessible in the ",(0,o.jsx)(n.code,{children:"Single Views"})," section. Selecting the Single View and the ",(0,o.jsx)(n.em,{children:"Single View Creator"})," associated, the configuration page with the list of config maps will include the No Code Aggregation by selecting the ",(0,o.jsx)(n.code,{children:"Aggregation"})," tab."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Example of an Aggregation configured with the No Code",src:i(243299).A+"",width:"1215",height:"709"})}),"\n",(0,o.jsx)(n.p,{children:"The new page allows creating an Aggregation from scratch with a clear visual of the Single View Data Model and with a simplified selection of fields based on the projection. It also includes a simpler way to add and manage dependencies and Join Dependencies, simplifying the configuration of the Single View Creator."}),"\n",(0,o.jsxs)(n.admonition,{type:"info",children:[(0,o.jsxs)(n.p,{children:["Before starting to configure the Aggregation with the No Code, ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/configuration/config_maps/erSchema#use-the-no-code",children:"a valid ER Schema must be selected"})," for the current Single View Creator."]}),(0,o.jsx)(n.p,{children:"Otherwise, a placeholder will remind you the need of an ER Schema, blocking the access to the Aggregation configuration page."})]}),"\n",(0,o.jsx)(n.h3,{id:"selection-of-the-base-projection",children:"Selection of the Base Projection"}),"\n",(0,o.jsxs)(n.p,{children:["If you don't have an ",(0,o.jsx)(n.em,{children:"aggregation"})," configuration file yet, or in case it has not been modified after creating the Single View Creator, opening the ",(0,o.jsx)(n.code,{children:"Aggregation"})," tab will show a placeholder that informs that a ",(0,o.jsx)(n.em,{children:"Base Projection"})," must be selected before starting configuring the aggregation."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Placeholder to inform the user that a Base Projection must be selected",src:i(335451).A+"",width:"1105",height:"710"})}),"\n",(0,o.jsxs)(n.p,{children:["The select field will show all the projections set in the selected ER Schema. The selection will represent the first dependency created in the aggregation that will be linked with the ",(0,o.jsx)(n.code,{children:"identifier"})," object of the ",(0,o.jsx)(n.a,{href:"/docs/15.0.1/products/fast_data/concepts/inputs_and_outputs#projection-change",children:"Projection Changes"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"how-to-map-fields",children:"How to map fields"}),"\n",(0,o.jsxs)(n.p,{children:["The page will now show the list of fields, as defined in the Single View Data Model page. You can even navigate in the nested structure of fields between fields of type ",(0,o.jsx)(n.code,{children:"object"})," or ",(0,o.jsx)(n.code,{children:"array of objects"})," to see the child fields and manage them as well."]}),"\n",(0,o.jsx)(n.p,{children:"Clicking on a field will open a drawer to the right side of the panel that allows you to map this field, by allowing the selection of an existing dependency and a field."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Detail of a field not mapped",src:i(989820).A+"",width:"324",height:"64"})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.em,{children:"Dependency"})," selection field will include a list of existing dependencies (on top) and all the other dependencies that can be connected (based on the conditions included inside the ER Schema)."]}),"\n",(0,o.jsxs)(n.p,{children:["Selecting a dependency will update the state of the ",(0,o.jsx)(n.em,{children:"Set Path"}),' button and its label: if the dependency already exists, the label will inform the user that a "Path is set", indicating that the Aggregation already includes all the necessary dependencies (from the base projection - thus that dependency linked to the Projection Changes document via the ',(0,o.jsx)(n.code,{children:"_identifier"})," condition) and it's already possible to select the field to complete the mapping: the ",(0,o.jsx)(n.em,{children:"Field"}),"  select field will now be available and the list will contain all the fields that can be used for the mapping."]}),"\n",(0,o.jsx)(n.p,{children:"The selection will automatically create the mapping. This can be noted also by the fact that all the warnings next to the name of the field will disappear."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Detail of a dependency field",src:i(991924).A+"",width:"684",height:"616"})}),"\n",(0,o.jsx)(n.h3,{id:"automatic-generation-of-dependencies-via-path",children:"Automatic generation of dependencies via Path"}),"\n",(0,o.jsxs)(n.p,{children:["In case the value selected in the ",(0,o.jsx)(n.em,{children:"Dependency"}),' select field is a dependency that does not exist yet, the "Path not set" text will still be there, and the ',(0,o.jsx)(n.code,{children:"Set Path"})," button can be clicked to open a modal that will introduce the user to a new way to create dependencies."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Selection of the path",src:i(701966).A+"",width:"1101",height:"665"})}),"\n",(0,o.jsxs)(n.p,{children:["The modal will include all the different paths to create all the needed dependencies to proceed with the mapping. Each path will represent a step composed of different projections connected via ER Schema ",(0,o.jsx)(n.code,{children:"one-on-one"})," conditions."]}),"\n",(0,o.jsxs)(n.p,{children:["In the example above, there are more ways to reach from ",(0,o.jsx)(n.em,{children:"pr_registry"})," to ",(0,o.jsx)(n.em,{children:"pr_dishes"}),", and it will be possible to select the path needed for the mapping. The modal also includes a canvas to the left side, similar to the ER Schema canvas, that shows the currently selected modal to help the user to visualize the path and make the correct choice."]}),"\n",(0,o.jsxs)(n.p,{children:["Click on ",(0,o.jsx)(n.code,{children:"Next"})," will move to the next step of the modal where the user will be prompted to select the condition for each step of the path."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Condition choices in selected path",src:i(968462).A+"",width:"1119",height:"669"})}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["To help to identify the correct condition, inside every ",(0,o.jsx)(n.em,{children:"Select a condition"}),' dropdown there will be an "',(0,o.jsx)(n.strong,{children:"i"}),'" icon on the right side: moving the mouse over this icon will show the query of the condition.']})}),"\n",(0,o.jsxs)(n.p,{children:["After selecting a condition for each step, a click on the ",(0,o.jsx)(n.code,{children:"Save"})," button will automatically create a dependency for each step of the selected path. The mapping can continue since the ",(0,o.jsx)(n.em,{children:"Field"})," select will be enabled and the value can be selected."]}),"\n",(0,o.jsx)(n.h3,{id:"manage-the-existing-dependencies",children:"Manage the existing dependencies"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.em,{children:"Set Path"}
1)," modal is not the only way to add new dependencies. These can be included manually via the ",(0,o.jsx)(n.em,{children:"Edit dependencies"})," button at the bottom of the page, followed by the number of dependencies already set. This button will open a different modal that will show all the existing dependencies, giving the possibility to add or delete some."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Dependency Editor",src:i(272519).A+"",width:"1102",height:"707"})}),"\n",(0,o.jsxs)(n.p,{children:["A click on the button ",(0,o.jsx)(n.code,{children:"+ Add dependency"})," will change the content of the modal to a form that will allow the user to select the starting projection, the target projection, the condition that connects said projection and - finally - a name to give to said dependency, in case you want to create ",(0,o.jsx)(n.a,{href:"#using-the-same-projection-as-a-dependency-multiple-times-under-different-conditions",children:"an alias"}),"."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Form to add a new dependency",src:i(983434).A+"",width:"1094",height:"706"})}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsx)(n.p,{children:"All those fields might be automatically populated in case there's only one option available."})}),"\n",(0,o.jsx)(n.p,{children:"After selecting all the fields, a click to save will add the dependency. On the other side, a click on the trash button next to each dependency will remove that dependency."}),"\n",(0,o.jsx)(n.p,{children:"A click on the `Save`` button is required to confirm the modifications, adding the created dependencies and removing the deleted ones."}),"\n",(0,o.jsx)(n.admonition,{type:"warning",children:(0,o.jsx)(n.p,{children:"Removing a dependency will remove also its references in the mapping (if there are any)"})}),"\n",(0,o.jsx)(n.h3,{id:"create-a-join-dependency-with-the-no-code",children:"Create a Join Dependency with the No Code"}),"\n",(0,o.jsxs)(n.p,{children:["In case it's necessary to map fields inside an array of objects, a new configuration object inside the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," must be created, with new dependencies starting from a ",(0,o.jsx)(n.a,{href:"#join-dependency",children:"Join Dependency"}),". In the No Code Aggregation, if you open an array of objects, another ",(0,o.jsx)(n.em,{children:"Edit dependencies"})," button will show up at the bottom of the section including the fields of said array of objects. In case the Join Dependency has not been set yet, the button will include a ",(0,o.jsx)(n.em,{children:"(0)"})," to signal that there are no dependencies set."]}),"\n",(0,o.jsx)(n.p,{children:"When clicking the button, the already mentioned modal will appear but with a placeholder to invite the user to create the Join Dependency."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"A placeholder is shown in case a join Dependency must be created",src:i(312660).A+"",width:"1099",height:"707"})}),"\n",(0,o.jsxs)(n.p,{children:["A click on the button ",(0,o.jsx)(n.code,{children:"Add dependency"})," will open the same form used to create regular dependencies, but with the important difference to have only starting projections included in the configuration of the parent field and to have only ",(0,o.jsx)(n.em,{children:"One To Many"})," conditions, necessary to map the array of objects."]}),"\n",(0,o.jsx)(n.p,{children:"Once the selection is completed, the modal will remain open to allow the user to add more dependencies that might be used to map the fields inside the array of objects."}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["The term ",(0,o.jsx)(n.code,{children:"path"})," refers to the route followed to reach the dependencies from which to retrieve the data to populate the fields of the single view.\nThe available paths are based on the ER schema that you must have previously defined in the ",(0,o.jsx)(n.em,{children:"Projection"})," section of the console and associated with the ",(0,o.jsx)(n.em,{children:"Single View Creator No Code"})," service. Since a projection can have various relationships, there could be multiple paths to reach the same dependency."]})}),"\n",(0,o.jsx)(n.h3,{id:"advanced-mode",children:"Advanced Mode"}),"\n",(0,o.jsxs)(n.p,{children:["On the bottom of the page, there's a switch that will change the ",(0,o.jsx)(n.code,{children:"Aggregation"})," view to its ",(0,o.jsx)(n.em,{children:"Advanced Mode"}),". This is will show the ",(0,o.jsx)(n.code,{children:"aggregation.json"})," file and additional custom function files that the user might want to include to use the advanced configuration of the Aggregation."]}),"\n",(0,o.jsxs)(n.p,{children:["In fact, with the No Code Aggregation, it will not be possible to include the ",(0,o.jsx)(n.a,{href:"#advanced-options",children:"advanced options"})," aforementioned: this has to be included in the Advanced Mode."]}
1),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Advanced Mode of the No Code Aggregation",src:i(164422).A+"",width:"1215",height:"706"})}),"\n",(0,o.jsx)(n.p,{children:"In this area, you can review the aggregation in its code format, and it's possible even to update the content inside, and to add or delete some parts of the configuration. Any update via Advanced Mode will be instantly reflected when switching back to the No Code."}),"\n",(0,o.jsx)(n.p,{children:"Despite this, it is possible to use the No Code Aggregation even if one or more fields have been mapped with one of the possible advanced options (such as the usage of a custom function from an external file, or a conditional value). In this case, the user can open the drawer related to the field, but it will be informed that an advanced configuration exists and the only way to make any change or review it is via the advanced mode."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Advanced mapping",src:i(166133).A+"",width:"356",height:"384"})}),"\n",(0,o.jsxs)(n.p,{children:["Also, the list of dependencies available via the ",(0,o.jsx)(n.em,{children:"Edit dependencies"})," button will inform the user of the usage of the ",(0,o.jsx)(n.a,{href:"#changing-the-query-that-finds-the-projection-based-on-their-identifier",children:"Identifier Query Mapping"})," or the usage of ",(0,o.jsx)(n.a,{href:"#using-conditional-expressions-on-dependencies-definitions-and-mappings",children:"conditional expressions"}),", but to review these advanced settings, the user will need to move to the Advanced Mode."]}),"\n",(0,o.jsx)(n.h3,{id:"error-and-warning-management",children:"Error and Warning management"}),"\n",(0,o.jsxs)(n.p,{children:["The No Code Aggregation will try to catch any error existing, especially on pre-existing ",(0,o.jsx)(n.code,{children:"aggregation.json"})," which might have an invalid structure or the JSON file is invalid."]}),"\n",(0,o.jsx)(n.p,{children:"In this case, the Advanced Mode will automatically be active, and it will not be possible to move to the No Code before to address these errors."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Wrong version in the Advanced Mode",src:i(578301).A+"",width:"1744",height:"794"})}),"\n",(0,o.jsx)(n.p,{children:"Moreover, the No Code Aggregation includes some warnings related to configurations that might not work correctly when running the Microservices and/or might lead to unexpected results."}),"\n",(0,o.jsx)(n.p,{children:"One of those warnings will be shown next to the field name, in case the field is not mapped, or an error icon in case the mapping is not valid."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"A field with a wrong mapping",src:i(310310).A+"",width:"325",height:"71"})}),"\n",(0,o.jsx)(n.p,{children:"Also, the drawer to the right side will inform you if the dependency or the field is not valid. Anyway, clicking on the field allows the selection of a valid value and proceed with the configuration."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Field mapping configuration with an non-existing field selected",src:i(396641).A+"",width:"377",height:"424"})}),"\n",(0,o.jsxs)(n.p,{children:["Errors in configured dependencies are visible inside the modal accessible via the ",(0,o.jsx)(n.em,{children:"Edit dependencies"})," button: in this case, the user will be informed if there are dependencies related to missing projections, or dependencies that are not reachable because the path is incomplete."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Non valid dependencies",src:i(576112).A+"",width:"1207",height:"781"})}),"\n",(0,o.jsxs)(n.p,{children:["In this case, it is highly suggested to remove the non-valid projections and re-add them (manually with the ",(0,o.jsx)(n.a,{href:"#automatic-generation-of-dependencies-via-path",children:"Set Path feature"}),")."]}),"\n",(0,o.jsx)(n.admonition,{type:"warning",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"oneOf"}),", ",(0,o.jsx)(n.code,{children:"anyOf"}),", ",(0,o.jsx)(n.code,{children:"allOf"}),", ",(0,o.jsx)(n.code,{children:"if"})," and ",(0,o.jsx)(n.code,{children:"$ref"})," JSON Schema operators would not make the Aggregation JSON validation fail, but are not handled in the No Code and could generate errors. Please try avoiding them when defining your Aggregation."]})}),"\n",(0,o.jsx)(n.h3,{id:"reset-the-aggregation",children:"Reset the Aggregation"}),"\n",(0,o.jsxs)(n.p,{children:["It is possible to reset the Aggregation and configure it from scratch from the ",(0,o.jsx)(n.em,{children:"Settings"})," tab, in case of mistakes in selecting the base Projection or using the ER Schema. In this tab, several general options regarding the Single View Creator are included and the first card, named ",(0,o.jsx)(n.em,{children:"General"})," shows the selected ER Schema and the selected Aggregation."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"General card that includes information on the selected ER Schema and Base Projection",src:i(144301).A+"",width:"1206",height:"172"})}),"\n",(0,o.jsxs)(n.p,{children:["A click on the ",(0,o.jsx)(n.code,{children:"Edit"})," button will open a modal that informs the user of the risks of losing the configured Aggregation before allowing the selection of a new ER Schema and/or a new base Projection. A change in one of the two values will reset the Aggregation."]})]})}function h(e={}){let{wrapper:n}={...(0,d.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},578301(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/advanced-more-with-errors-8951e62e067d1de1bf60b61dff75da17.png"},166133(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/advanced_mapping-cdfffe757e972b076673f714caacd9fc.png"},164422(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/advanced_mode-6e12d248b55ca24eb7c4aa4199c3ee0d.png"},243299(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/aggregation_example-0613ac7fa4f1c2f18c9fdaede95430e4.png"},335451(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/base_projection-a427bc88d486dd165d3dd7e081e0fa98.png"},968462(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/condition_selection_in_path-23cbecc654a1c1c885bbdf3ef1082b86.png"},272519(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/dependency_editor-b92751150094419ad3f8d3d7b70fee9e.png"},983434(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/dependency_editor_form-5b50abc5715544dee08cc517a9ced306.png"}
1,576112(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/dependency_editor_with_errors-d20664068c6e6613fb92482a6de79c01.png"},991924(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/dependency_field_detail-f0b649deda5a1e4f9578d6a9fbca15b2.png"},989820(e,n,i){i.d(n,{A:()=>t});let t="data:image/png;base64,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"},310310(e,n,i){i.d(n,{A:()=>t});let t="data:image/png;base64,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"},144301(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/general_card-af5d7c0e2c8145a3e4883303c26d13bc.png"},312660(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/join_dependency_placeholder-27c52334c6d44c6271f56e7fabdf0ed2.png"},396641(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/mapping_drawer_with_errors-e37bf3201e2112aa85592363453b1fc1.png"},701966(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/path_selection-17efe0b5f7779d4da8c844d30a0b1180.png"},28453(e,n,i){i.d(n,{R:()=>s,x:()=>a});var t=i(296540);let o={},d=t.createContext(o);function s(e){let n=t.useContext(d);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),t.createElement(d.Provider,{value:n},e.children)}}}]);

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.