GlideRecord

The GlideRecord class is one of the most ubiquitous and useful classes in ServiceNow. Its primary function is to query a database table, and present values corresponding to each record in that table, that matches a given query. It can also be used to add, modify, or delete records. A GlideRecord object consists of properties with names corresponding to each field in the table. In the client-side Glide API, these properties usually contain strings, whereas on the server-side API, these properties contain GlideElement JavaScript Objects with their own methods and properties.

Initialize

A GlideRecord object must first be initialized by using the new keyword (which calls the initialize() constructor method) and passing in a table name as a string. This tells the new GlideRecord object what table any subsequent queries or new records are created on.

Example usage

Initialize a new GlideRecord object on the Incident table, and store it in the gr variable:

var grIncident = new GlideRecord('incident');
grIncident.addActiveQuery();
grIncident.query();
while (grIncident.next()) {
    //do something
}

addQuery()

The addQuery() method of the GlideRecord class can be called in three different ways, depending on whether one, two, or three arguments are supplied to it. If one argument is passed into the addQuery() method, then it'll assume that the argument is an encoded query. An encoded query is a single string that represents all of the conditions in a single query (or even multiple queries)!

There isn't any official documentation on how to construct an encoded query (though it isn't hard to figure out), but there is a very easy way to build one yourself—simply navigate to the table you want to run the query on, and use the query builder! For example, here's a query on the Incident table where the Assigned to user is active, and either the Incident is active, or the State is set to New, In Progress, or On Hold:

addQuery()

You can build a filter on a given table using the query builder, and then apply that same filter to your GlideRecord query by simply right-clicking the last condition in the query breadcrumbs above the list view, and clicking on Copy query:

addQuery()

This is similar in functionality to the addEncodedQuery() method.

You'll see an example of this single-argument usage in the following section. On the other hand, if you pass in two arguments, then it is assumed that the first argument is the field name, and the second argument is the expected value.

Finally, if you pass in three arguments to the addQuery() method, you may specify not only a field and value, but an operator between them. Operators that you can use as the second argument in this case, include some rather standard operators with obvious meaning, as well as some others for more advanced functionality. You'll find a list of available operators in the following table.

Available query operators

The following table displays the query operators (which can be specified as the second argument in a GlideRecord addQuery() method call). These operators determine how the database query is formed on the server.

Operator

Meaning

= (equals)

The field (the first argument) must be equal to the value (the third argument).

> (greater than)

The field specified must contain a value greater than the value specified in the third argument.

< (less than)

The field must contain a value less than the value specified.

>= (greater than or equal to)

The field in the first argument must contain a value that is greater than or equal to the value specified in the third argument.

<= (less than or equal to)

The field must contain a value less than or equal to the value specified.

STARTSWITH

The field must contain a value which, as a string, starts with the value specified.

CONTAINS

The value of the field must contain the string specified in the third argument.

DOES NOT CONTAIN

The opposite of CONTAINS. The value of the field must not contain the value specified.

IN

If this is the second argument when calling the addQuery() method, then the third argument should contain a comma-separated list of one or more values.

The value of the field specified in the first argument must then be one of the values specified in the third.

Example: gr.addQuery('state', 'IN', '1,3,5');

NOT IN

The reverse of IN, that is, the value of the field specified in the first argument must not also exist within the comma-separated list of values specified within the third argument.

ENDSWITH

The field value must end with the value specified in the third argument.

INSTANCEOF

This is a special operator that is meant to be used on base or parent tables, to determine if a given record's table is an instance of a given sub-table. In this case, you would specify sys_class_name as the first argument, INSTANCEOF as the second argument, and the other table name as the third argument. For example, you might want to query the base system task table, and only see requests. The query for that would look like this:

gr.addQuery('sys_class_name', 'INSTANCEOF', 'sc_request');    

This way, even if you were to extend the sc_request table, you would still see all of those records in the results of this query, since they would be in a table that was an instance of (extended from) the sc_request table.

Example usage

With a single argument, that argument is assumed to be an encoded query:

var gr = new GlideRecord('incident'); 
var encodedQuery = 'assigned_to.active=true^active=true^ORstateIN1,2,3'; 
gr.addQuery(encodedQuery); 

With two arguments, it is assumed that the first is a field name, and the second is a value to compare that field's value to for equivalency:

var gr = new GlideRecord('incident'); 
gr.addQuery('number', 'INC0012345'); 

With three arguments, the first is assumed to be a field name, the second is an operator, and the third is a value to compare the value of the first to:

var gr = new GlideRecord('incident'); 
gr.addQuery('closed_at', '>', gs.nowDateTime()); 

Or you can use the CONTAINS operator:

var gr = new GlideRecord('incident'); 
gr.addQuery('number', 'CONTAINS', '123'); 

Any of the operators listed in the table earlier in this chapter can be used in place of CONTAINS in the preceding code snippet.

addActiveQuery()

addActiveQuery() is a simple API method that accepts no arguments, but adds a query requiring that the active field must be true. It has identical functionality as if you were to write gr.addQuery('active', 'true').

addNullQuery() and addNotNullQuery()

Both addNullQuery() and addNotNullQuery() accept a single argument; a string, indicating which field should be checked.

When addNullQuery() is called on a GlideRecord object, it adds a condition to your query, stating that the field passed into the method call must be null (empty).

On the other hand, when the addNotNullQuery() method is called with a field name as an argument, a condition is added to your query stating just the opposite—that the field must contain a value—any value. It must be NotNull.

Example usage

Here, on lines two and three, we add one NullQuery and one NotNullQuery, respectively for two different fields:

var gr = new GlideRecord('sc_request'); 
gr.addNullQuery('assigned_to');  
gr.addNotNullQuery('assignment_group'); 
gr.query(); 
while (gr.next()) { 
    //do something 
} 

In this case, our query will return results where the assignment_group field is not blank, but the assigned_to field is blank.

canRead(), canWrite(), canCreate(), and canDelete()

These four methods can be called on a GlideRecord without any arguments, and each will return a Boolean true/false value, indicating whether the record can be read, written to, created, or deleted by the current user.

These methods take no arguments, because they apply to the entire record rather than to a given field.

Example usage

While there are use cases for calling these methods on GlideRecords inside of scripts, they are most useful inside of Condition fields; for example, those which determine visibility of UI actions, as you can see in the screenshot after the example code snippet:

current.canCreate() && gs.hasRole('itil') 
Example usage

These two conditions check whether the user can create records in that table, and whether the user has the itil role.

Tip

Documenting your code—telling other developers who might read it, both what you're doing, and (most importantly) why—is critically important to being a good developer. However, condition fields must be written on a single line. There is a character limit in that field, but whenever possible, you can still comment your code using inline comments like so:

current.canRead() /*User can read this record*/ && gs.hasRole('admin') /*AND the user has the Admin role*/ 

deleteRecord() and deleteMultiple()

These two methods are for the deletion of one or more records from the database.

It should be made clear that deletion of records in ServiceNow generally is, and should be, a rare occurrence. Whenever possible, it is best to deactivate or otherwise mark a record as no longer in use, for historical and tracking purposes.

Neither deleteRecord() nor deleteMultiple() take any arguments, as both are called as methods of a specific GlideRecord object upon which they act. However, the similarities end there, as the behavior and usage of these methods are quite different.

deleteRecord() is used to delete a single record (in a GlideRecord) from the database. deleteMultiple() on the other hand, is used to delete all database records that match a given query. However, it is important to remember this: do not use deleteMultiple() on tables that contain currency fields. Instead, delete all such records one at a time, using deleteRecord() in this case.

Example usage

The deleteMultiple() method can be called either after the query(), or without it, but without calling next():

var query = 'active=false^closed_atRELATIVELT@year@ago@2'; //Tickets closed more than 2 years ago 
var gr = new GlideRecord('incident'); 
gr.addQuery(query); 
gr.deleteMultiple(); 

In this case, I'm running this on the Incident table, which in my instance does not have any currency fields.

Again, this method should not be called on any tables that contain currency fields due to a limitation in ServiceNow. It should also not be used in conjunction with setLimit(). Instead, use the following deleteRecord() syntax:

var query = 'active=false^closed_atRELATIVELT@year@ago@2'; //Tickets closed more than 2 years ago 
var gr = new GlideRecord('incident'); 
gr.addQuery(query); 
gr.query(); 
while (gr.next()) { 
    gr.deleteRecord(); 
} 

Both of these blocks of code will delete all records matching the encoded query stored in the query variable. The query pulls a list of all incidents that are not active, which were closed more than two years ago, as a company might want to delete records after two years to keep the Task [task] table light.

get()

The get() method is an excellent shorthand for a very simple, single-condition query. It will only return one record. This method can accept either one or two arguments.

If one argument is supplied, it is expected that it'll be the sys_id of a record in the table specified when the GlideRecord object was instantiated.

If two arguments are specified, it is expected that the first argument will be a field name, and the second will be the value to filter by on that field. You cannot specify three arguments, which means it is not possible to use any special operators such as CONTAINS or >.

The get() method will only return one record, similar to using gr.setLimit(1);, or only calling gr.next(); once. Even if multiple records are returned from your query (if two arguments are specified).

Calling the GlideRecord get() method effectively combines the steps of adding a query, calling .query(), and calling .next(), all into one step. The following example demonstrates how it works.

Example usage

With one argument, get() expects a sys_id:

var recordSysID = '46f09e75a9fe198100f4ffd8d366d17b'; 
var gr = new GlideRecord('incident'); 
if (gr.get(recordSysID)) {
    //do something with the record 
} else {
    //do something when the record is not found
}

With two arguments, get() expects that the first argument will be the field name, and the second will be a value to compare the field value to. The following code block will return one record—the first record that matches the specified query:

var gr = new GlideRecord('incident'); 
if (gr.get('number', 'INC0000025')) {
    //do something with the record 
} else {
    //do something when the record is not found
}

getDisplayValue()

As we learned in an earlier chapter, each table has one value that's set as the display value. This is the value that is displayed when the record is referenced in reference fields or elsewhere in the system. This field is usually, but not always, unique. The reference field can be changed by altering the dictionary record for a column in the table, but only one field can be the display value in a given table at one time. Setting a new field's Display value field to true will automatically set that field to false on the previous display value's dictionary entry, thus ensuring that there is only one display value at a time.

getDisplayValue() is quite simple, as it accepts no arguments, and returns the value of whatever field is set as the display value for the record upon which it's called.

Example usage

The following code snippet will set the value of the displayVal variable to INC0010014. INC0010014 happens to be the value of the Number [number] field of the incident for which the sys_id was passed into the get() API, since number is the field set as the display value in the Incident table:

var gr = new GlideRecord('incident'); 
gr.get('46f09e75a9fe198100f4ffd8d366d17b'); 
var displayVal = gr.getDisplayValue();  

The returned value is a primitive (a string), so the displayVal variable would now contain a string containing the Incident number.

getValue() and getUniqueValue()

Both the getValue() and getUniqueValue() methods will return a value from the GlideRecord upon which they're called.

getUniqueValue() accepts no arguments, and simply returns the primary key (the sys_id) of the record.

getValue() on the other hand, can return the value from any table column (including sys_id). It accepts one argument—a field name, and will return the value therein.

Example usage

getUniqueValue() doesn't take any arguments, and it's a quick and easy way to retrieve the sys_id of a given record.

getValue() on the other hand, returns the value of a specific field or column. This can be the sys_id column, or any other column that might contain a value; simply pass the name of the field into getValue(), and it will return a primitive (string) value matching the contents of the field on the specified record:

var gr = new GlideRecord('incident'); 
gr.get('46f09e75a9fe198100f4ffd8d366d17b'); 
var sysIDVal = gr.getValue('sys_id'); 
var incNumber = gr.getValue('number'); 

hasNext()

hasNext() is a simple method that returns a Boolean value, indicating whether or not there are more records returned from a GlideRecord query, which can be accessed using .next().

If, for example, your query returns three records, you might call .next() after the query to get the first record. At this point, hasNext() will return true. Calling next() again to get the second record will leave us with one left, so once again, hasNext() will return true. However, calling next() one more time will populate the third and final record into the GlideRecord object. There being no further records to grab, if we call hasNext() once more at this point, it will return false.

Example usage

Here, we use hasNext() as the loop condition, and call next() inside the loop:

var query = 'active=false^closed_atRELATIVELT@year@ago@2';  
var gr = new GlideRecord('incident'); 
gr.addQuery(query); 
gr.query(); 
while (gr.hasNext()) { 
    gr.next(); 
    //do something 
}

We could simplify this loop by using .next() in the loop condition, since it returns true (when called) if it was successful in pulling a new record, and false if it wasn't. next() is documented later in this chapter. There are use-cases for using hasNext() over next(), but next() is far more common.

initialize() and insert()

If you want to create a new record in the database, you're generally going to need to call two methods: initialize() and insert(), although it is possible to generate a new record by simply using insert().

Neither method takes any arguments, and their uses are functionally linked.

When you create a new GlideRecord, you're effectively generating an object that has the potential to be populated with some data. Think of this object like a blank spreadsheet. Whether you want to read data out of the spreadsheet, or save data to it, the first thing you need to do is figure out what the column headers should be. This will tell you what data goes where! This is essentially the function of the initialize() API.

When you create a new GlideRecord, define your filter query, and run the .query() method, it talks to the database and sets up the GlideRecord object so that it contains a property for each field that exists in the database, for the table you've specified. Think of these empty properties like column headers in our imaginary spreadsheet.

If we call next(), the system gets the next (or first) record in the database, and populates all of the GlideRecord object properties (like columns) with the values corresponding to that one record. If we use setValue() to modify one of these values, and then call update(), the system takes that modified database row and loads it into the database over the existing one, overwriting the old values.

The initialize() method of a GlideRecord—unlike that of a script include—does something similar to what query() does, in that it gets the basic structure of the database table that the GlideRecord corresponds to, filling in the header columns of our imaginary spreadsheet. However, rather than calling next() to populate the GlideRecord properties with an existing value from the database, we can populate it ourselves, and use insert() to push the values we've populated to the database. Any values we don't specify will get their default value, if one is specified.

Note

The short version

The initialize() method prepares a GlideRecord to be populated by your script, while the insert() method pushes any values you populated it with, to the database.

Example usage

Here, we begin by declaring our GlideRecord object, initializing it on the Incident table, and setting a few values.

When we call the setValue() method on lines 3 and 4, we populate a GlideElement object property within the GlideRecord object, corresponding to the field specified in the first argument of the setValue() method call. We set the value to the value specified in the second argument of the setValue() call:

var gr = new GlideRecord('incident'); 
gr.initialize(); 
gr.setValue('short_description', 'Example record'); 
gr.setValue('description', 'This is a test.'); 
gr.insert();  

Finally, on line 5, we call the insert() method, which pushes the GlideRecord object to the database, at which point a new record is created with the values you specified, and the default values used for any unspecified fields.

It is also possible to insert on an existing GlideRecord, thus effectively creating a duplicate. Consider the following code, which does not use the initialize() API:

var gr = new GlideRecord('incident');
gr.setLimit(1);
gr.addActiveQuery();
gr.query();
gr.next(); //Load the first active Incident from the database
gr.setValue('active', 'false'); //Set the active field to false
gr.insert(); //Insert a new record with our modification

First, we load the first active Incident record from the database, then we modify it by setting the active field to false. However, until we call the update() API, the changes only exist in our local GlideRecord variable (gr).

Rather than using the update() method of the GlideRecord API, which would have modified the existing record in the database, we used insert().

next()

The next() method of the GlideRecord class should be called after a query(). Its function is to grab one row from the database table we specified when declaring our GlideRecord object, and populate that object with the values from each column/field in that record/row. This allows you to modify the record and send it back to the database using setValue() and update(), or you can read values from the record and use them elsewhere in your script by using getValue().

The next() method takes no arguments, and returns a Boolean which is true or false depending on whether it successfully found another record or not respectively; thus, the next() method call can simultaneously be used as a loop condition.

Example usage

Here, we use the next() method both as an iterator to move to the next record in the database, and as a condition (since it returns true whenever it's successful) in the condition of the while loop:

var gr = new GlideRecord('incident'); 
gr.addQuery('active', 'true'); 
gr.query(); 
while (gr.next()) { 
    //do something 
}

Tip

Don't get confused between the return value of the next(), and hasNext() methods. next() will return true if it found a next record in the list matching your query filter, and will have already loaded it into the GlideRecord object. On the other hand, hasNext() will return true if there exists a next record in the database, but it won't load it up yet. The former tells you about the record you're currently (trying to) iterate into, and the latter looks at the next record to see if one exists—but does not move into it like next() does.

orderBy() and orderByDesc()

orderBy() and orderByDesc() both sort the results of your query before they're returned, so that when you iterate through the results using the next() method, you get the results in the appropriate order.

The orderBy() and orderByDesc() methods both accept one argument: The name of a field in the database table specified when instantiating the GlideRecord object you're calling this method on. This is the field that will either be sorted low-to-high/a-to-z/past-to-present if you used the orderBy() method, or the opposite if you called orderByDesc().

Example usage

orderBy() and orderByDesc() are both called in exactly the same way. Simply specify the field you'd like to sort the results by after your query is run:

var gr = new GlideRecord('incident'); 
gr.addQuery('active', 'true'); 
gr.orderBy('priority'); 
gr.query(); 
while (gr.next()) { 
    //do something 
}

These APIs should be called prior to calling the query() method, as the database will sort the query results before returning them to your script.

query()

The query() method of the GlideRecord class is one that (unless you use get() to retrieve a single record) is used any time you want to use a GlideRecord to retrieve data from the database.

When you call the query() method, you're submitting the query to the database. The result is retrieving some data which you can think of like a spreadsheet/list of results. You can iterate through the rows of those results using the next() method.

Example usage

Except when using get(), or in a situation such as a business rule where a GlideRecord is already defined for you, calling the query() method is usually a necessary step before you can do anything to any records that already exist in the database:

var gr = new GlideRecord('incident'); 
gr.addActiveQuery(); 
gr.orderBy('priority'); 
gr.query(); 
while (gr.next()) { 
    //do something 
}

setAbortAction()

This method is one that's most commonly used inside of business rules to abort whatever database action was being performed that triggered the business rule to fire. Calling this method on the current object in a business rule means that no changes will be committed to the database.

There are other ways to prevent a database action (data policies and ACLs, for example), but this allows you some finer-grain control over how and when it happens. For example, you might write a script in a business rule which checks several conditions—even conditions based on external records or system properties—and determines whether to abort the database action based on that.

The setAbortAction() method accepts one argument: a Boolean. Whatever Boolean value this method was last called with when the script finishes running, will determine whether the database action is actually aborted or not.

In other words, calling setAbortAction(true) in one part of your script, and then later calling setAbortAction(false), will result in the database action not being cancelled.

Example usage

This example assumes it's running inside of a before business rule, which means that the current object is pre-populated with a GlideRecord corresponding to whichever record was inserted or updated, triggering the business rule to run:

if (current.getValue('active') === 'false') { 
    current.setAbortAction(true); 
} 
if (gs.hasRole('admin')) { 
    current.setAbortAction(false); 
}

You may also default to aborting the action, and then conditionally allow it. In the following example, the operation will only be aborted if the record is not active:

current.setAbortAction(true);
if (current.getValue('active') === 'true') {
    current.setAbortAction(false);
}

setLimit()

The setLimit() method of the GlideRecord class takes one argument: a number corresponding to the maximum number of records that should be returned from the database. This can be used to limit potential performance implications of a large query, or by combining it with orderBy() or orderByDesc(), and can further extend the usefulness of this method.

Example usage

Let's look at an example where you want to have a script pull up to 10 incidents from the database in order to assign them to a particular user, whose sys_id is stored in the assignee variable. But you don't just want to assign 10 random incidents from the queue; you would probably want to make sure that you got the highest priority ones first, so we order by the Priority field:

var gr = new GlideRecord('incident'); 
gr.addQuery('assignment_group', assignmentGroup); 
gr.orderBy('priority'); 
gr.setLimit(10); 
gr.query(); 
while (gr.next()) {
    gr.setValue('assigned_to', assignee); 
    gr.update(); 
}

setValue()

Except for setting journal fields, setValue() is used to update any field value in a GlideRecord object. After updating a field value, you must submit the new data to the database using a method such as insert(), update(), or updateMultiple().

setValue() accepts two arguments: A field name, and a new value for that field. It does not return a value.

You'll often see code (including out-of-the-box code!) that does not use setValue(), but instead sets the field directly like so: current.short_description = 'Example short description';. This is not a best practice. It will technically work (usually), but because of JavaScript's type coercion and pass-by-reference features, this can cause issues that are extremely difficult to troubleshoot and pin down.

The same rule applies to the getValue() method: It should be used nearly any time you need to retrieve a value from a GlideReord field. There are some exceptions to this rule, but you should get into the habit of using getValue() and setValue() as standard practice.

Tip

You can learn more about the importance of using getValue() and setValue(), as well as the exceptions to this rule, by checking out the article at pbr.sngeek.com.

Example usage

Here, we use get() with two arguments to retrieve a RITM (from the sc_req_item table) by number, and then we use setValue() and gs.getUserID() to set the assigned_to field to the current user. Finally, we use the update() method to commit the change to the database:

var ritmGR = new GlideRecord('sc_req_item'); 
ritmGR.get('number', 'RITM0010455'); 
ritmGR.setValue('assigned_to', gs.getUserID()); 
ritmGR.update(); 

setWorkflow()

The setWorkflow() method accepts one argument: a Boolean true/false value. This argument will determine whether any business rules should be triggered by any database actions performed by your GlideRecord script. For example, if you make a change and call the update() method, calling setWorkflow() and passing in false will prevent any business rules that would normally be triggered by that update from running. It also prevents other script engines (such as the workflow engine) and audit scripts from running.

This is exceptionally useful for when you need to make a mass update to a lot of records but you don't want to trigger any additional actions. For example, perhaps an error caused all incidents generated over the past week to be created without a Description field value, but you want it to default to the same value as the Short description when no other value is specified. Once you've corrected the Default value field on that column's dictionary record, you might then want to find all records where the Description field is empty but the Short description field is not, and set the former to the latter.

To avoid running business rules and sending notifications as a result of that change, you can use the setWorkflow(false) API.

This method returns no value.

Example usage

The following script would result in a database record being updated, but no business rules would be triggered by this update:

var grRitm = new GlideRecord('sc_req_item'); 
grRitm.get('number', 'RITM0010455'); 
grRitm.setValue('assigned_to', gs.getUserID()); 
grRitm.setWorkflow(false); 
grRitm.update(); 

update() and updateMultiple()

Both update() and updateMultiple() will result in a database update. The main difference is that update() operates on one record at a time, whereas updateMultiple() updates any and all records returned from your GlideRecord query, without using next() to iterate through each one. update() returns the Sys ID of the updated record.

update() accepts one optional argument: the reason for the update. This reason will be logged in the audit history for the updated record.

updateMultiple() on the other hand, accepts no arguments, and returns no value. It should not be used in conjunction with setLimit().

Tip

While it's possible to modify a field's value by using gr.ield_name = 'new_value';, this is generally not best except with journal fields. This is especially critical while using updateMultiple(). You should never directly set a value like that before using updateMultiple(). You must use setValue() instead, or the update could ignore the query filter, updating every record in the table. That would be bad. Each field in the database table becomes an element of the GlideRecord object (gr in the previous snippet). This element is not just a string or number, but a specific Object type, called a GlideElement. More on that API later in this chapter.

Example usage

Here, we use update() to modify a single record:

var ritmGR = new GlideRecord('sc_req_item'); 
ritmGR.get('number', 'RITM0010455'); 
ritmGR.setValue('assigned_to', gs.getUserID()); 
ritmGR.update(); 

In the following example, we will demonstrate the updateMultiple() method by assigning one user (stored in the assignee variable) to all unassigned Incident tickets:

var gr = new GlideRecord('incident');  
gr.addNullQuery('assigned_to'); //checks for blank assignee field
gr.query();  
gr.setValue('assigned_to', assignee);  
gr.updateMultiple(); 

Note that we don't use the next() method here at all, because we're using the updateMultiple() method. We are also sure to use setValue(), rather than directly setting the value as a property.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.222.47