sabell2012
Mega Sage
Mega Sage

NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER, ACCENTURE.

 

DIFFICULTY LEVEL:    INTERMEDIATE to ADVANCED
Assumes having taken the class SSNF and has good intermediate to advanced level of knowledge and/or familiarity with Scripting in ServiceNow.


In this article I will present a couple of different methods I use to locate a record in a complex object array.

 

This is the third of three articles I wanted to write concerning object arrays. My previous two were:

 

Community Code Snippets - Three Methods to Sort an Object Array

Community Code Snippets - Removing Duplicates From an Object Array

 

I suggest going through those before playing with the code in this example.

 

Additionally, you will need to work through the following Mini-Labs in order to use underscore.js and the JavaScriptExtensions code:

 

Mini-Lab: Adding Underscore.js Into ServiceNow

Mini-Lab: Extending the JavaScript Array Object with findIndex

 

Preparation: Use the following code for all of the examples in this article. All of these examples are to be run in Scripts - Background.

 

// Set up for all of the following examples. Get 10 records from the Incident table
var incidentRecords = new GlideRecord('incident');
incidentRecords.setLimit(10);
incidentRecords.query();

var incidentList=[];

while(incidentRecords.next()) {
	var incident = {};
	incident.sys_id = incidentRecords.sys_id + '';
	incident.number = incidentRecords.getValue('number');
	incidentList.push(incident);
}

var incidentID = '46ee8c2fa9fe198100623592c70d643e';
gs.info(JSON.stringify(incidentList));
// ------- Code examples ------- 

 

EXAMPLE 1:

 

This is my preferred method. It does not require a library in Global or Scoped, and works with existing out-of-the-box ServiceNow JavaScript libraries.

 

// ------- Code examples ------- 

var incidentLocated = incidentList.filter(function(element) { return element.sys_id === incidentID; })[0];
gs.info('---> Array.filter:\n\tsys_id: {0} - {1}', [incidentLocated.sys_id, incidentLocated.number]);

 

This gives the following result:

 

*** Script: [{"sys_id":"1c741bd70b2322007518478d83673af3","number":"INC0000060"},{"sys_id":"1c832706732023002728660c4cf6a7b9","number":"INC0009002"},{"sys_id":"46b66a40a9fe198101f243dfbc79033d","number":"INC0000009"},{"sys_id":"46b9490da9fe1981003c938dab89bda3","number":"INC0000010"},{"sys_id":"46c03489a9fe19810148cd5b8cbf501e","number":"INC0000011"},{"sys_id":"46c88ac1a9fe1981014de1c831fbcf6d","number":"INC0000012"},{"sys_id":"46cebb88a9fe198101aee93734f9768b","number":"INC0000013"},{"sys_id":"46e18c0fa9fe19810066a0083f76bd56","number":"INC0000014"},{"sys_id":"46ee0924a9fe198100f1cf78c198454a","number":"INC0000021"},{"sys_id":"46ee8c2fa9fe198100623592c70d643e","number":"INC0000024"}]
*** Script: ---> Array.filter: sys_id: 46ee8c2fa9fe198100623592c70d643e - INC0000024

However, you don't get the actual index location back; if you care about it that is.

 

EXAMPLE 2:

 

So, let me demonstrate a way of doing the same thing with the underscore.js library. Here you can see that there is a way of retrieving the location of the record based on the ID.  

 

// ------- Code examples ------- 

gs.include('underscorejs.min');
var indexUS = _.chain(incidentList).pluck("sys_id").indexOf(incidentID).value();
incidentUS = incidentList[indexUS];
gs.info('---> Underscore: index:{2}\n\tsys_id: {0} - {1}', [incidentUS.sys_id, incidentUS.number, indexUS]);

 

Produces the exact same results:

 

*** Script: [{"sys_id":"1c741bd70b2322007518478d83673af3","number":"INC0000060"},{"sys_id":"1c832706732023002728660c4cf6a7b9","number":"INC0009002"},{"sys_id":"46b66a40a9fe198101f243dfbc79033d","number":"INC0000009"},{"sys_id":"46b9490da9fe1981003c938dab89bda3","number":"INC0000010"},{"sys_id":"46c03489a9fe19810148cd5b8cbf501e","number":"INC0000011"},{"sys_id":"46c88ac1a9fe1981014de1c831fbcf6d","number":"INC0000012"},{"sys_id":"46cebb88a9fe198101aee93734f9768b","number":"INC0000013"},{"sys_id":"46e18c0fa9fe19810066a0083f76bd56","number":"INC0000014"},{"sys_id":"46ee0924a9fe198100f1cf78c198454a","number":"INC0000021"},{"sys_id":"46ee8c2fa9fe198100623592c70d643e","number":"INC0000024"}]
*** Script: ---> Underscore: index:9.0 sys_id: 46ee8c2fa9fe198100623592c70d643e - INC0000024

 

The only problem I have with this example is in maintenance. I have to comment it a bit so that it explains what exactly is happening.

 

 

EXAMPLE 3:

 

So finally, if you implement the new ECMA6 polyfill for Array.findIndex you get the same functionality as the underscore.js example, but it is easier to implement (and future-proof; as when ServiceNow finally implements the ECMA6 functionality).  

 

// ------- Code examples ------- 

gs.include('JavaScriptExtensions');
var indexFI = incidentList.findIndex(function(element) { return element.sys_id == incidentID; });
var incidentFindIndex = incidentList[indexFI];
gs.info('---> FindIndex: index:{2}\n\tsys_id: {0} - {1}', [incidentFindIndex.sys_id, incidentFindIndex.number, indexFI]);

 

Produces the exact same results:

 

*** Script: [{"sys_id":"1c741bd70b2322007518478d83673af3","number":"INC0000060"},{"sys_id":"1c832706732023002728660c4cf6a7b9","number":"INC0009002"},{"sys_id":"46b66a40a9fe198101f243dfbc79033d","number":"INC0000009"},{"sys_id":"46b9490da9fe1981003c938dab89bda3","number":"INC0000010"},{"sys_id":"46c03489a9fe19810148cd5b8cbf501e","number":"INC0000011"},{"sys_id":"46c88ac1a9fe1981014de1c831fbcf6d","number":"INC0000012"},{"sys_id":"46cebb88a9fe198101aee93734f9768b","number":"INC0000013"},{"sys_id":"46e18c0fa9fe19810066a0083f76bd56","number":"INC0000014"},{"sys_id":"46ee0924a9fe198100f1cf78c198454a","number":"INC0000021"},{"sys_id":"46ee8c2fa9fe198100623592c70d643e","number":"INC0000024"}]
*** Script: ---> FindIndex: index:9.0 sys_id: 46ee8c2fa9fe198100623592c70d643e - INC0000024

 

Again, this example would require some commenting just to make it clear to a maintenance coder what is going on.

 

OTHER FUTURE EXAMPLES:

 

The following are examples that should work in a Scoped application set for ECMA6+ is implemented in ServiceNow:

 

// ------- Code examples ------- 

// ecma 6+ --- doesn't work yet ... sniff!
var incidentMap = incidentList.map(x => x.says_id).indexOf(incidentID);
gs.info('---> Map:\n\tsys_id: {0} - {1}', [incidentMap.sys_id, incidentMap.number]);

// ecma 6+ --- nor this! makes me want to weep...
var incidentFindIndex = incidentList.findIndex(x => x.sys_id === incidentID);
gs.info('---> FindIndex:\n\tsys_id: {0} - {1}', [incidentFindIndex.sys_id, incidentFindIndex.number]);

// ecma 6+ --- This works, but only in scoped apps!
var index = incidentList.reduce((i, item, index) => item.sys_id === incidentID ? index : i, -1);
var incidentIndex = incidentList[index];
gs.info('---> reduce: index: {2}\n\tsys_id: {0} - {1}', [incidentIndex.sys_id, incidentIndex.number, incidentIndex]);

 

Results I get when run in a scoped application:

 

x_0462_myniftyapp: [{"sys_id":"1c741bd70b2322007518478d83673af3","number":"INC0000060"},{"sys_id":"1c832706732023002728660c4cf6a7b9","number":"INC0009002"},{"sys_id":"46b66a40a9fe198101f243dfbc79033d","number":"INC0000009"},{"sys_id":"46b9490da9fe1981003c938dab89bda3","number":"INC0000010"},{"sys_id":"46c03489a9fe19810148cd5b8cbf501e","number":"INC0000011"},{"sys_id":"46c88ac1a9fe1981014de1c831fbcf6d","number":"INC0000012"},{"sys_id":"46cebb88a9fe198101aee93734f9768b","number":"INC0000013"},{"sys_id":"46e18c0fa9fe19810066a0083f76bd56","number":"INC0000014"},{"sys_id":"46ee0924a9fe198100f1cf78c198454a","number":"INC0000021"},{"sys_id":"46ee8c2fa9fe198100623592c70d643e","number":"INC0000024"}]
x_0462_myniftyapp: ---> Map: sys_id: undefined - undefined
x_0462_myniftyapp: ---> FindIndex: sys_id: undefined - undefined
x_0462_myniftyapp: ---> reduce: index: 9 sys_id: 46ee8c2fa9fe198100623592c70d643e - INC0000024


So, you can see that there are a several ways to retrieve a record from an object array. Explore this a bit, and you might find other ways (yes, there are more).

 

Some "light" additional reading on Polyfills:

 

https://reference.codeproject.com/javascript/reference/global_objects/array/filter 

https://reference.codeproject.com/javascript/reference/global_objects/array/foreach 

https://reference.codeproject.com/javascript/reference/global_objects/array/find 

https://reference.codeproject.com/javascript/Reference/Global_Objects/Array/findIndex

 

Enjoy!

Steven Bell.

 

If you find this article helps you, don't forget to log in and mark it as "Helpful"!

 

sabell2012_0-1699709259871.png


Originally published on: 7-30-2018 08:19 PM

I updated the code and brought the article into alignment with my new formatting standard.