- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
GlideFilter is used to determine if a GlideRecord meets the conditions specified in an encoded query string. For instance, it's used in the business rule condition builder to determine under which conditions the business rule must run. It's not well documented and its usage is slightly different between global and scoped apps, so there seems to be some confusion, especially on how it's used with regular expressions. I'll share what I know here and update this based on your feedback/additions/corrections.
The only official documentation available is Scoped GlideFilter API Reference. However, its variation is available in the global scope as well. Let's take a look at how they're used and how they're different (as of the Helsinki release).
SCOPED GlideFilter
Scoped GlideFilter is an object that is used without having to instantiate. It has only one method:
boolean checkRecord(GlideRecord gr, string filter, boolean matchAll) // returns true if gr meets the conditions specified in filter
gr: a single GlideRecord
filter: an encoded query string
matchAll: (Optional) if true (default), all conditions in filter must match to return true; if false, any single true condition returns true (see below)
Here's an example:
var gr = new GlideRecord('incident');
gr.query();
var filter = 'active=true^state=2'; // active && state == 'In Progress'
while (gr.next()) { // iterate through records
if (GlideFilter.checkRecord(gr, filter)) gs.info(gr.number); // test each record for the filter conditions
}
This returns all incident records that are active and the state is 'In Progress'. Some points to note are:
- GlideFilter is not instantiated (no need for new GlideFilter()).
- GlideFiter.checkRecord() is applied to each record after gr.query() is executed. In other words, GlideFilter is not used by gr.query().
USING MATCH_RGX FOR REGULAR EXPRESSION MATCH
GlideFilter also allows the use of regular expressions in the filter using the MATCH_RGX operator. Here's an example, modified from the previous one:
var gr = new GlideRecord('incident');
gr.query();
var filter = 'active=true^state=2^numberMATCH_RGXINC.*'; // active && state == 'In Progress' && /^INC.*$/m.test(number)
while (gr.next()) { // iterate through records
if (GlideFilter.checkRecord(gr, filter)) gs.info(gr.number); // test each record for the filter conditions
}
This returns all incident records that are active, the state is 'In Progress' and the number starts with 'INC' (since all incident numbers start with 'INC', this doesn't really do anything). What's not well known and often a source of confusion is that MATCH_RGX already includes /^ and $/m, the start and end of string in multiline mode; the regular expression filter condition specified, therefore, is what comes between /^ and $/m. So
fieldMATCH_RGXcondition
is equivalent to, in JavaScript,
/^condition$/m.test(field)
Also, the test is case sensitive (we'll see below that there's a way to make this case insensitive in the global scope but not in scoped GlideFilter). Some examples and their JavaScript equivalents are
fieldMATCH_RGXabc === /^abc$/m.test(field) // field exactly matches "abc"
fieldMATCH_RGXabc.* === /^abc.*$/m.test(field) // field starts with "abc"
fieldMATCH_RGX.*abc === /^.*abc$/m.test(field) // field ends with "abc"
fieldMATCH_RGX.*abc.* === /^.*abc.*$/m.test(field) // field contains "abc"
It's worthwhile noting that MATCH_RGX is not available in GlideRecord's .addEncodedQuery() method (I wish it was); this indicates there are different flavors of encoded queries in ServiceNow.
GLOBAL GlideFilter
The examples used above for Scoped GlideFilter also work in the global scope. In addition, Global GlideFilter provides the following features:
new GlideFilter(string filter, string title)
filter: an encoded query string
title: title of the filter
boolean match(GlideRecord gr, boolean matchAll) // returns true if gr meets the conditions specified in filter from GlideFilter instance
gr: a single GlideRecord
matchAll: if true, all conditions in filter must match to return true; if false, any single true condition returns true (see below). This is not optional, unlike in .checkRecord().
void setCaseSensitive(boolean caseSensitivity) // sets whether .match() is case sensitive (does not apply to .checkRecord())
caseSensitivity: if true, .match() is case sensitive (does not apply to .checkRecord()).
Here are some additional properties and methods:
boolean caseSensitive // true if .match() is case sensitive
string filter // encoded query string of the filter
string getFilter() // returns encoded query string of the filter
string title // title of the filter
string getTitle() // returns the title of the filter
void setDisplayTitle(String displayTitle) // sets the display title of the filter
string getDisplayTitle() // returns the display title of the filter (returns title if display title not set)
string script // a string representing the source code of the JavaScript function for evaluating the filter conditions
Here's an example:
var gr = new GlideRecord('incident');
gr.query();
var filter = 'active=true^state=2^numberMATCH_RGXinc.*'; // active && state == 'In Progress' && /^inc.*$/i.test(number)
var gf = new GlideFilter(filter, '');
gf.setCaseSensitive(false);
while (gr.next()) { // iterate through records
if (gf.match(gr, true)) gs.info(gr.number); // test each record for the filter conditions
}
Just like what we saw earlier, this returns all incident records that are active, the state is 'In Progress' and the number starts with 'inc' (case insensitive). .match() works similarly to .checkRecord(), but with an added benefit of evaluating case-sensitive or insensitive matches.
matchAll FLAG
The .script property, which shows the JavaScript function that evaluates the filter conditions, gives a clue on how the matchAll flag works. Using the above example:
matchAll = true
function trecord() {return !!(current.active == true && current.state.toString().toLowerCase() == 2 && RegExp('^inc.*$','mi').test(current.number.toString()));}trecord();
matchAll = false (effectively all conditions become OR conditions)
function trecord() {if (current.active == true ) return true;if (current.state == 2 ) return true;if (RegExp('^inc.*$','m').test(current.number.toString()) ) return true; return false;}trecord();
SUMMARY
Here's a summary of how GlideFilter is used in both global and scoped apps:
- GlideFilter is used to test encoded query filter conditions one record at a time; it can't be used to filter a bulk record set.
- GlideFilter supports regular expression matches using the MATCH_RGX operator: fieldMATCH_RGXcondition is equivalent to /^condition$/m.test(field) in JavaScript, with the /^ and $/m automatically added.
- In scoped apps,
- GlideFilter is an object that is used without having to instantiate.
- GlideFilter has only one method: .checkRecord().
- In global apps,
- GlideFilter can be used the same way as in scoped apps.
- GlideFilter can be instantiated, which gives two main methods: .match(), .setCaseSensitive().
- Encoded queries in GlideFilter support MATCH_RGX but those used in GlideRecord's .addEncodedQuery() don't.
HELPFUL LINKS
- Scoped GlideFilter API Reference
- RegEx in condition builder
- Matches Regex in Condition Builder
- Using the condition Builder
- Ask the Expert: Regular Expressions Part 1 - TechNow Ep 31
- SN Pro Tips — Understanding Dynamic Filters & Checking a Record Against a Filter Using GlideFilter
- Case Insensitive Filter
UPDATES
2016-11-21 corrected matchAll parameter and added .script example output; corrected title parameter; added multiline flag to regular expressions; added additional properties and methods for GlideFilter().
Please feel free to connect, follow, post feedback / questions / comments, share, like, bookmark, endorse.
John Chun, PhD PMP ![]() | ![]() |
- 15,425 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.