From 73528966a33814ef3dc9b90cd871e0153414519f Mon Sep 17 00:00:00 2001 From: JohanDC-1999 <82451675+JohanDC-1999@users.noreply.github.com> Date: Sat, 4 Oct 2025 13:30:47 +0200 Subject: [PATCH 1/6] Create readme.md --- .../Background Scripts/Duplicate Finder/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Server-Side Components/Background Scripts/Duplicate Finder/readme.md diff --git a/Server-Side Components/Background Scripts/Duplicate Finder/readme.md b/Server-Side Components/Background Scripts/Duplicate Finder/readme.md new file mode 100644 index 0000000000..d622c0abed --- /dev/null +++ b/Server-Side Components/Background Scripts/Duplicate Finder/readme.md @@ -0,0 +1 @@ +# Contribution From 780630a5d8d2d172b26b6d516b68bafa9893805d Mon Sep 17 00:00:00 2001 From: JohanDC-1999 <82451675+JohanDC-1999@users.noreply.github.com> Date: Sat, 4 Oct 2025 13:33:37 +0200 Subject: [PATCH 2/6] Create script.js which finds duplicates --- .../Duplicate Finder/script.js | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Server-Side Components/Background Scripts/Duplicate Finder/script.js diff --git a/Server-Side Components/Background Scripts/Duplicate Finder/script.js b/Server-Side Components/Background Scripts/Duplicate Finder/script.js new file mode 100644 index 0000000000..c8cc7e3f11 --- /dev/null +++ b/Server-Side Components/Background Scripts/Duplicate Finder/script.js @@ -0,0 +1,66 @@ +function findDuplicates(tableName, fieldName) { + /**************************************/ + /*** Basic error handling on inputs ***/ + /**************************************/ + + // Check if table exists + if (!gs.tableExists(tableName)) { + // MODIFIED: Switched to string concatenation + gs.info('Table "' + tableName + '" does not exist.'); + return; + } + + // Check if field exists + var fieldGr = new GlideRecord('sys_dictionary'); + fieldGr.addQuery('name', tableName); + fieldGr.addQuery('element', fieldName); + fieldGr.query(); + + if (!fieldGr.next()) { + gs.print('No field called "' + fieldName + '" on the "' + tableName + '" table.'); + return; + } + + /***************************************/ + /*********** Find duplicates ***********/ + /***************************************/ + var duplicateJson = {}; // Store the duplicate records + var duplicateGroupCount = 0; // Counts the number of groups of duplicates + + var duplicateAggregate = new GlideAggregate(tableName); + duplicateAggregate.addAggregate('COUNT', fieldName); + duplicateAggregate.groupBy(fieldName); + duplicateAggregate.addHaving('COUNT', '>', 1); // More than 1 means it is a duplicate + duplicateAggregate.addNotNullQuery(fieldName); // Ignore records where the field is empty + duplicateAggregate.query(); + + while (duplicateAggregate.next()) { + duplicateGroupCount++; + var fieldValue = duplicateAggregate.getValue(fieldName); + var countInGroup = duplicateAggregate.getAggregate('COUNT', fieldName); + duplicateJson[fieldValue] = countInGroup; + } + + /***************************************/ + /********** Print the results **********/ + /***************************************/ + + // No duplicates found + if (Object.keys(duplicateJson).length === 0) { + gs.print('No duplicates found for field "' + fieldName + '" on table "' + tableName + '".'); + return; + } + + // Duplicates were found + gs.print("Found " + duplicateGroupCount + " groups of duplicates:"); + + for (var key in duplicateJson) { + gs.print('Value "' + key + '" has ' + duplicateJson[key] + ' occurrences.'); + } +} + +// Update below values to find duplicates +var tableName = 'sys_user'; // ADD: Table you want for duplicates +var fieldName = 'email'; // ADD: Field that you want to check for duplicates + +findDuplicates(tableName, fieldName); From 508c90daa608481084d2be942415cb17f2aaadf3 Mon Sep 17 00:00:00 2001 From: JohanDC-1999 <82451675+JohanDC-1999@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:31:15 +0200 Subject: [PATCH 3/6] Update readme.md --- .../Duplicate Finder/readme.md | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Server-Side Components/Background Scripts/Duplicate Finder/readme.md b/Server-Side Components/Background Scripts/Duplicate Finder/readme.md index d622c0abed..4f1000b477 100644 --- a/Server-Side Components/Background Scripts/Duplicate Finder/readme.md +++ b/Server-Side Components/Background Scripts/Duplicate Finder/readme.md @@ -1 +1,24 @@ -# Contribution +## ServiceNow Duplicate Record Finder +A simple server-side script for ServiceNow that finds and reports on duplicate values for any field on any table. It uses an efficient GlideAggregate query and formats the results into a clean, readable report. + +### How to Use +This script is designed to be run in **Scripts - Background** or as a Fix Script. +1. Navigate: Go to **System Definition > Scripts - Background** (or type sys.scripts.do in the filter navigator). +2. Copy Script: Copy the entire contents of the script.js file. +3. Paste and Configure: Paste the script into the "Run script" text box. At the bottom, modify the function call to target your desired table and field: + ```js + // CONFIGURE YOUR QUERY HERE + findDuplicates('your_table_name', 'your_field_name'); + ``` + For example, to find duplicate email addresses in the User table: + ```js + findDuplicates('sys_user', 'email'); + ``` + To find incidents with the same short description: + ```js + findDuplicates('incident', 'short_description'); + ``` + + +4. Run Script: Click the "Run script" button. The results will be displayed on the screen below the editor. + From 6845da808eb37f14dfad233106251fd3338bc38e Mon Sep 17 00:00:00 2001 From: JohanDC-1999 <82451675+JohanDC-1999@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:34:47 +0200 Subject: [PATCH 4/6] Update script.js --- .../Background Scripts/Duplicate Finder/script.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Server-Side Components/Background Scripts/Duplicate Finder/script.js b/Server-Side Components/Background Scripts/Duplicate Finder/script.js index c8cc7e3f11..d2a7b6d654 100644 --- a/Server-Side Components/Background Scripts/Duplicate Finder/script.js +++ b/Server-Side Components/Background Scripts/Duplicate Finder/script.js @@ -1,3 +1,9 @@ +// Update ONLY below values to find duplicates +var tableName = 'sys_user'; // ADD: Table you want for duplicates +var fieldName = 'email'; // ADD: Field that you want to check for duplicates + +findDuplicates(tableName, fieldName); + function findDuplicates(tableName, fieldName) { /**************************************/ /*** Basic error handling on inputs ***/ @@ -59,8 +65,3 @@ function findDuplicates(tableName, fieldName) { } } -// Update below values to find duplicates -var tableName = 'sys_user'; // ADD: Table you want for duplicates -var fieldName = 'email'; // ADD: Field that you want to check for duplicates - -findDuplicates(tableName, fieldName); From a945dff378bff2b7d01224161ce242a80497e024 Mon Sep 17 00:00:00 2001 From: JohanDC-1999 <82451675+JohanDC-1999@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:45:28 +0200 Subject: [PATCH 5/6] Update readme.md --- .../Background Scripts/Duplicate Finder/readme.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Server-Side Components/Background Scripts/Duplicate Finder/readme.md b/Server-Side Components/Background Scripts/Duplicate Finder/readme.md index 4f1000b477..3ca613a445 100644 --- a/Server-Side Components/Background Scripts/Duplicate Finder/readme.md +++ b/Server-Side Components/Background Scripts/Duplicate Finder/readme.md @@ -5,18 +5,21 @@ A simple server-side script for ServiceNow that finds and reports on duplicate v This script is designed to be run in **Scripts - Background** or as a Fix Script. 1. Navigate: Go to **System Definition > Scripts - Background** (or type sys.scripts.do in the filter navigator). 2. Copy Script: Copy the entire contents of the script.js file. -3. Paste and Configure: Paste the script into the "Run script" text box. At the bottom, modify the function call to target your desired table and field: +3. Paste and Configure: Paste the script into the "Run script" text box. Add the table to search in `tableName` and the field to search for duplicates in `fieldName` ```js - // CONFIGURE YOUR QUERY HERE - findDuplicates('your_table_name', 'your_field_name'); + // Update ONLY below values to find duplicates + var tableName = ''; // ADD: Table you want for duplicates + var fieldName = 'field_name'; // ADD: Field that you want to check for duplicates ``` For example, to find duplicate email addresses in the User table: ```js - findDuplicates('sys_user', 'email'); + var tableName = 'sys_user'; + var fieldName = 'email';; ``` To find incidents with the same short description: ```js - findDuplicates('incident', 'short_description'); + var tableName = 'incident'; + var fieldName = 'short_description'; ``` From 098ad4e916ed4b95055877333666534e24ad77fe Mon Sep 17 00:00:00 2001 From: JohanDC-1999 <82451675+JohanDC-1999@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:46:29 +0200 Subject: [PATCH 6/6] Update script.js to work on inherited fields --- .../Background Scripts/Duplicate Finder/script.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Server-Side Components/Background Scripts/Duplicate Finder/script.js b/Server-Side Components/Background Scripts/Duplicate Finder/script.js index d2a7b6d654..3318e5faa0 100644 --- a/Server-Side Components/Background Scripts/Duplicate Finder/script.js +++ b/Server-Side Components/Background Scripts/Duplicate Finder/script.js @@ -1,6 +1,6 @@ // Update ONLY below values to find duplicates -var tableName = 'sys_user'; // ADD: Table you want for duplicates -var fieldName = 'email'; // ADD: Field that you want to check for duplicates +var tableName = 'incident'; // ADD: Table you want for duplicates +var fieldName = 'short_description'; // ADD: Field that you want to check for duplicates findDuplicates(tableName, fieldName); @@ -17,12 +17,9 @@ function findDuplicates(tableName, fieldName) { } // Check if field exists - var fieldGr = new GlideRecord('sys_dictionary'); - fieldGr.addQuery('name', tableName); - fieldGr.addQuery('element', fieldName); - fieldGr.query(); - - if (!fieldGr.next()) { + var gr = new GlideRecord(tableName); + gr.initialize(); + if (!gr.isValidField(fieldName)) { gs.print('No field called "' + fieldName + '" on the "' + tableName + '" table.'); return; }