Get all downstream relationship(child relations) from Relationship Table(cmdb_rel_ci)for each record
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-22-2024 12:04 PM - edited 08-22-2024 12:51 PM
Requirement -
Irrespective of the CI Class, We want to get all the sys_ids of 'child relationship record' in the Array.
Let's suppose, parent records "A" is having two child(downstream relationship) "Ab" and "Ac", These two child record has two more child relationships("Abc" and Abd).
Parent - "A"
Child of Parent "A" are - Ab, Ac
Check child of Ab(now Ab is parent and it's child is) -> Abc
Check child of Abc(now Abc is parent and it's child is) -> No child left and return array
Check child of Ac(now Ac is parent and it's child is) -> Abd
Check child of Abd(now Abd is parent and it's child is) -> No child left and return array
Total child records of "A" is Ab, Ac, Abc, Abd. These 4 record's sys_id will get stored in an Array for further use.
Solution - This has been done via recursion successfully. (In script, Parent records are all type of Business application 'CI Class')
try {
var vArrChild = [];
var vChild = '';
var gaRelation = new GlideAggregate('cmdb_rel_ci');
gaRelation.addEncodedQuery('parent.sys_class_name=cmdb_ci_business_app');
gaRelation.groupBy('parent');
gaRelation.groupBy('child');
//gaRelation.setLimit(1);
gaRelation.query();
while (gaRelation.next()) {
//gs.print(gaRelation.getDisplayValue('child') + " & " + gaRelation.getDisplayValue('parent'));
vChild = gaRelation.getValue('child');
vArrChild.push(getChildRelation(vChild));
gs.info("Child "+vArrChild);
}
} catch (err) {
gs.info("Child ERROR: " + err);
}
function getChildRelation(vChild) {
var vArrChild = [];
vArrChild.push(vChild);
var vNestedChild = '';
var gaRelation = new GlideAggregate('cmdb_rel_ci');
gaRelation.addQuery('parent', vChild);
gaRelation.groupBy('parent');
gaRelation.groupBy('child');
gaRelation.query();
while (gaRelation.next()) {
// gs.print("rec " + gaRelation.getDisplayValue('child') + " & " + gaRelation.getDisplayValue('parent'));
vNestedChild = gaRelation.getValue('child');
vArrChild.push(getChildRelation(vNestedChild));
}
//gs.print('rec func end');
return vArrChild;
}
This code works correctly.
Challenge:
This code works for such records which has 100 or 500 childs etc. But we have few record which has more than 1000 child. And ServiceNow doesn't support more than 1000 function calls or recursion call and stops the execution of script. PFB error caught in catch block.
ERROR: org.mozilla.javascript.RhinoStackOverflowException: Maximum JavaScript call depth of 1000 exceeded
Any ideas or suggestion would be appreciated.
I am already trying to reduce the child record criteria with business.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-22-2024 12:16 PM - edited 08-22-2024 12:21 PM
I would use GlideRecord instead of GlideAggregate. Since you are not using anything from here:
And I don't see any stop condition in your script. The following is from a script include used by a Dynamic Filter to get subordinate users for the current user. (sys_user table manager field.)
function mySubordinateUsers() {
var userManager = gs.getUserID();
// gs.info('mySubordinateUsers: Manager = ' + userManager);
var users = []; // users to check
var subUsers = []; // found subordinate users
// add the current "user" to support check for resursion in data
users.push(userManager); // starting user to get subordinates
subUsers.push(userManager);
var foundNew = true;
//Get the users where current user is the 'manager'
while (foundNew) {
var subs = [];
for (i = 0; i < users.length; i++) {
foundNew = getSubordinateUsers(users[i], subs);
}
// clear array to process and add subordinate users to array
users.length = 0;
for (i = 0; i < subs.length; i++) {
// check to see if found sub is in the current list, prevent resursion
if (subUsers.indexOf(subs[i]) == -1) {
subUsers.push(subs[i]);
users[i] = subs[i]; // reload users array
}
}
// if (foundNew)
// gs.info("processing users: " + users);
}
// gs.info("user list = " + subUsers);
return subUsers;
}
function getSubordinateUsers(mgrUser, usrArray) {
// next get the list of child manager users
var foundRec = false;
var subUsr = new GlideRecord('sys_user');
subUsr.addQuery('manager', mgrUser);
subUsr.query();
// gs.info("SubordinateUsers: Found " + subUsr.getRowCount() + " record where manager = " + mgrUser);
while (subUsr.next()) {
usrArray.push(subUsr.getValue('sys_id'));
// gs.info("SubordinateUsers: adding " + subUsr.user_name + " as subordinate");
foundRec = true;
}
// gs.info("SubordinateUsers: subordinate users = " + usrArray);
return foundRec;
}
Th
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-22-2024 12:21 PM
I am using groupBy here and GA functionality is required to me later when i accommodate this script in some other logic.
No stop condition is required as whenever it doesn't find the child record, it returns the array.
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-22-2024 12:35 PM - edited 08-22-2024 12:36 PM
Are you checking for the following scenario: A children - Ac, Ab
Ac children - Aca, AcB
Aca children - A
Seems you script never stops.