logo

NJP

Community Code Snippets - Finding a Record in an Object Array

Import · Aug 30, 2016 · article

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 - undefinedx_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%5Fobjects/array/filter

https://reference.codeproject.com/javascript/reference/global%5Fobjects/array/foreach

https://reference.codeproject.com/javascript/reference/global%5Fobjects/array/find

https://reference.codeproject.com/javascript/Reference/Global%5FObjects/Array/findIndex

Enjoy!

Steven Bell.

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

image

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

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

View original source

https://www.servicenow.com/community/developer-blog/community-code-snippets-finding-a-record-in-an-object-array/ba-p/2283300