/**
* Get records with duplicate values in multiple fields, and return a list of the records'
* counts and the dupe fields' values.
*
* @param {string} tableName - The table to check for duplicates. Must be a string.
*
* @param {string|string[]} arrDupeFields - The fields to check for duplicates.
* Must be a string or an array of strings.
*
* @param {string|string[]} [nonBlankFields=[]] - This optional parameter, if specified, will
* be an array of strings consisting of the names of the fields which should not be allowed
* to be blank when checking for duplicates.
* To put it another way, if any of the fields specified in the `nonBlankFields` array are
* blank, then the record should not be considered a duplicate.
* Note that the fields specified in nonBlankFields do NOT need to also be specified in
* arrDupeFields.
*
* @param {boolean} [getDupeSysIds=false] - If true, the sys_ids of the records with the
* duplicate values will be included in the returned object. If false, they will not be
* included.
* This may have a performance impact, as it requires an additional query for each
* duplicate combination, so use with caution.
* Default is false.
*
* @returns {{dupeCount: (*|number), fields: {}}[]} - An array of objects, each object
* representing a confluence of duplicate values in the specified fields - a specific
* combination of field values - and the number of records that have that combination of
* those values in the specified fields.
*/
function getMultiFieldDupes(tableName, arrDupeFields, nonBlankFields, getDupeSysIds) {
var gaMyTableDuplicate, grDupe, iNonBlankField, iDupeField, objDupeRecord;
var arrDupeRecords = [];
var dupeCount = 0;
/***** INPUT VALIDATION *****/
getDupeSysIds = (typeof getDupeSysIds === 'boolean') ? getDupeSysIds : false;
if (typeof tableName !== 'string' || !tableName) {
throw new Error(
'getMultiFieldDupes(): tableName must be a string consisting of a valid ' +
'table name in the ServiceNow database.'
);
}
if ( //If arrDupeFields is not an array or a string, or if it's an array but it's empty
typeof arrDupeFields === 'undefined' ||
!arrDupeFields ||
(!Array.isArray(arrDupeFields) && typeof arrDupeFields !== 'string') ||
!arrDupeFields.length
) {
throw new Error(
'getMultiFieldDupes(): arrDupeFields must be a string with a single ' +
'field name, or an array of strings - each string representing a ' +
'field name in the ' + tableName + ' table.'
);
}
//If arrDupeFields is a string, convert it to an array.
if (typeof arrDupeFields === 'string') {
arrDupeFields = arrDupeFields.split(',');
}
//If nonBlankFields is undefined, null, or an empty string, set it to an empty array.
//If it's a string, convert it to an array.
if (typeof nonBlankFields === 'undefined' || !nonBlankFields) {
nonBlankFields = [];
} else if (typeof nonBlankFields === 'string') {
//Splitting just in case the input data is a comma-separated string - which it
// shouldn't be, but I don't trust anyone who calls this code. They seem sus.
nonBlankFields = nonBlankFields.split(',');
} else if (!Array.isArray(nonBlankFields)) {
//If it's not a string or an array or undefined, throw an error because wth am I s'posed to do with that
throw new Error(
'getMultiFieldDupes(): nonBlankFields must be a string with a single ' +
'field name, or an array of strings - each string representing a ' +
'field name in the ' + tableName + ' table.'
);
}
/***** ACTUALLY DOING THE THING *****/
gaMyTableDuplicate = new GlideAggregate(tableName);
gaMyTableDuplicate.addAggregate('COUNT');
//Group by each field in the arrDupeFields array
for (
iDupeField = 0;
iDupeField < arrDupeFields.length;
iDupeField++
) {
gaMyTableDuplicate.groupBy(arrDupeFields[iDupeField]);
}
//If any nonBlankFields were specified, add a query to exclude records where
// any of those fields are blank.
for (
iNonBlankField = 0;
iNonBlankField < nonBlankFields.length;
iNonBlankField++
) {
gaMyTableDuplicate.addNotNullQuery(nonBlankFields[iNonBlankField]);
}
//Only show records with more than one match (duplicates)
gaMyTableDuplicate.addHaving('COUNT', '>', 1);
gaMyTableDuplicate.query();
while (gaMyTableDuplicate.next()) {
dupeCount = gaMyTableDuplicate.getAggregate('COUNT');
//Populate the arrDupeRecords array with some info about the records that have duplicates
objDupeRecord = {
"dupeCount": dupeCount,
"fields": {}
};
//For each field in the arrDupeFields array, add that field's value to
// the objDupeRecord.fields object.
for (
iDupeField = 0;
iDupeField < arrDupeFields.length;
iDupeField++
) {
objDupeRecord.fields[arrDupeFields[iDupeField]] = gaMyTableDuplicate.getValue(arrDupeFields[iDupeField]);
}
if (getDupeSysIds) {
objDupeRecord.dupe_sys_ids = [];
//Add the sys_ids of all the records that have this combination of dupe fields in objDupeRecord.dupe_sys_ids:
grDupe = new GlideRecord(tableName);
for (
iDupeField = 0;
iDupeField < arrDupeFields.length;
iDupeField++
) {
grDupe.addQuery(arrDupeFields[iDupeField], objDupeRecord.fields[arrDupeFields[iDupeField]]);
}
grDupe.query();
while (grDupe.next()) {
objDupeRecord.dupe_sys_ids.push(grDupe.getUniqueValue());
}
}
arrDupeRecords.push(objDupeRecord);
}
return arrDupeRecords;
}
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter