Once upon a time, there was a global, instantiatable “GlideFilter” object. It was a little ugly and unintuitive, but it technically worked; usually. Nowadays though, the GlideFilter object is a scoped-API object (also available to the global scope) that is not instantiatable, and which has… some problems.
ServiceNow is aware of these problems, but - although they continue to use GlideFilter in their scoped apps (such as for vulnerability grouping rules in the Vulnerability application, which have been broken by the use of GlideFilter as of London - PRB1329737) - they have refused to fix the issues (PRB605673).
“What problems”, you ask? - Let’s say you’ve got an Incident with the number “INC000123”. You might have an encoded query that looks something like this:
active=true^number=inc000123
If you use that encoded query to filter the list view on the Incident table, that’ll work just fine.
It’ll also work just fine if you use that query in a script, such as this:
var grIncident = new GlideRecord('incident'); grIncident.addEncodedQuery('active=true^number=inc000123'); grIncident.setLimit(1); grIncident.query(); if (grIncident.next()) { gs.print('Found INC000123!'); //Works just fine }
But let’s say you’ve already got a GlideRecord (let’s call it current), and you want to compare it to an encoded query, to see if the record matches the query. You can imagine a scenario in which you’ve got a “condition” field on one record, and you want to compare the condition in that field to another record. What then?
That’s what GlideFilter is (supposed to be) for. The idea is to write a single line of code, and get a boolean indicating whether the GlideRecord matches the encoded query, like so:
var doesRecordMatch = GlideFilter.checkRecord(current, 'active=true^number=inc000123');
However, even if you have an active Incident with the number INC000123, and even if the query works just fine in a scripted query and in the list filter, the above line of code will actually set the doesRecordMatch variable to false.
Why? - Because GlideFilter.checkRecord(), is case-sensitive.
Why again? - I have no idea. It’s not documented that it’s case-sensitive, and I can’t think of a reason why it should be case-sensitive, but it is, and there’s no way to make it not case-sensitive.
Okay, yeah, but what’s the solution
Alright, enough bitching about GlideFilter, here’s the solution. It’s actually fairly simple (which makes it all the more frustrating that they’ve said they won’t fix it, but I digress); simply copy the below script into a Script Include in your instance.
Name: BetterGlideFilter
Accessible from: All application scopes
Application: Global
/* No need to instantiate. Just call like so: BetterGlideFilter.checkRecord(current, 'active=true^number=INC000123', false); */ var BetterGlideFilter = { /** * Check a GlideRecord (gr) against an encoded query. Returns true if the GlideRecord matches the query, or false if it does not. * If the encoded query contains multiple queries (indicated by containing "^NQ"), then you can set matchAll to true to make sure that checkRecord() only returns true if ALL conditions are met. * @param {GlideRecord} gr - A GlideRecord object containing the record to check the query against. * @param {String} queries - A string containing the encoded query (or queries) to compare the GlideRecord to. For multiple queries, use the "^NQ" operator or build your multi-tier query using the query builder in the list view. * @param {Boolean} [matchAll=false] - Whether to require that all queries (separated by "^NQ") should match in order for checkRecord() to return true. This is an optional parameter (default: false) and only applies when the provided query contains multiple queries (indicated by "^NQ" in the encoded query string). * @returns {boolean} - Whether the provided GlideRecord matches the provided query. */ checkRecord: function(gr, queries, matchAll) { var i, encQuery; var newQueryToken = '^NQ'; var queryMatches = false; //Set default value for matchAll matchAll = (typeof matchAll == 'undefined') ? (false) : (matchAll); //Get an array of queries if (queries.indexOf(newQueryToken) >= 0) { //If the encoded query contains multiple queries queries = queries.split(newQueryToken); } else { queries = [queries]; } /* Loop through each query. If matchAll is true and one of the queries doesn't match, we can stop there and return false. If matchAll is false, and one of the queries DOES match, we can stop there and return true. Otherwise, keep looping until we run out of queries, and return the value in queryMatches */ for (i = 0; i < queries.length; i++) { encQuery = queries[i]; queryMatches = this._check(gr, encQuery); //If matchAll is true, but the query did not match, return false. if (matchAll && !queryMatches) { return false; } //If matchAll is false, and the query matched, return true. if (!matchAll && queryMatches) { return true; } //If matchAll is false and the query does NOT match, then continue checking. //If matchall is true and the query DOES match, continue checking. } return queryMatches; }, /** * Private helper method for checking one query at a time against a GlideRecord. Used by .checkRecord(). * @param {GlideRecord} gr * @param {String} query * @returns {Boolean} * @private */ _check: function(gr, query) { /* Here, I'm using GlideRecord with .setLimit(1) because my query is SO specific (being by sys_id) that this is the most efficient method in almost every scenario. More information in this blog post: https://community.servicenow.com/community?id=community_blog&sys_id=a2bc2e25dbd0dbc01dcaf3231f9619df */ var grCheck = new GlideRecord(gr.getTableName()); grCheck.addQuery('sys_id', gr.getValue('sys_id')); grCheck.addEncodedQuery(query); grCheck.setLimit(1); grCheck.query(); return grCheck.hasNext(); } };
With the above Script Include in your instance, you’ve simply got to update any references to “GlideFilter”, to instead reference “BetterGlideFilter”, and you now have a case-agnostic solution.
Update 6/6/20
A brilliant fellow ServiceNow developer, János Szentpáli, reached out to me today, to let me know that he’s found that, despite what HI support has told us, GlideFilter does in fact have an (undocumented) mechanism by which to force it to be case-insensitive: by using it as a constructor!
Of course, one should be wary of becoming heavily reliant on undocumented functionality; but the functionality that he’s demonstrated does have at least one advantage over the tool I’ve written above. It can be used against records which have not yet been committed to the database. Certainly if your use-case relies on that ability, then you’d probably be best-off using the method that János describes in his article!
Check out his excellent article here, for more info.
- March 2024
-
February 2024
- Feb 12, 2024 5 Lessons About Programming From Richard Feynman
- July 2023
- May 2023
- April 2023
-
December 2022
- Dec 13, 2022 ServiceNow Developers: BE THE GUIDE!
- October 2022
-
August 2022
- Aug 23, 2022 Using .addJoinQuery() & How to Query Records with Attachments in ServiceNow
- Aug 18, 2022 Free, Simple URL Shortener for ServiceNow Nerds (snc.guru)
- Aug 16, 2022 How to Get and Parse ServiceNow Journal Entries as Strings/HTML
- Aug 14, 2022 New tool: Get Latest Version of ServiceNow Docs Page
- March 2022
- February 2022
- May 2021
- April 2021
- February 2021
-
November 2020
- Nov 17, 2020 SN Guys is now part of Jahnel Group!
- September 2020
- July 2020
-
January 2020
- Jan 20, 2020 Getting Help from the ServiceNow Community
- December 2019
- November 2019
-
April 2019
- Apr 21, 2019 Understanding Attachments in ServiceNow
- Apr 10, 2019 Using Custom Search Engines in Chrome to Quickly Navigate ServiceNow
- Apr 4, 2019 Set Catalog Variables from URL Params (Free tool)
- Apr 1, 2019 Outlook for Android Breaks Email Approvals (+Solution)
- March 2019
-
February 2019
- Feb 27, 2019 Making Update Sets Smarter - Free Tool
-
November 2018
- Nov 29, 2018 How to Learn ServiceNow
- Nov 6, 2018 ServiceNow & ITSM as a Career?
- October 2018
- September 2018
-
July 2018
- Jul 23, 2018 Admin Duty Separation with a Single Account
-
June 2018
- Jun 19, 2018 Improving Performance on Older Instances with Table Rotation
- Jun 4, 2018 New Free Tool: Login Link Generator
-
May 2018
- May 29, 2018 Learning ServiceNow: Second Edition!
- April 2018
- March 2018
-
February 2018
- Feb 11, 2018 We have a new book!
- November 2017
-
September 2017
- Sep 12, 2017 Handling TimeZones in ServiceNow (TimeZoneUtil)
- July 2017
-
June 2017
- Jun 25, 2017 What's New in ServiceNow: Jakarta (Pt. 1)
- Jun 4, 2017 Powerful Scripted Text Search in ServiceNow
- May 2017
- April 2017
-
March 2017
- Mar 12, 2017 reCAPTCHA in ServiceNow CMS/Service Portal
-
December 2016
- Dec 20, 2016 Pro Tip: Use updateMultiple() for Maximum Efficiency!
- Dec 2, 2016 We're Writing a Book!
-
November 2016
- Nov 10, 2016 Chrome Extension: Load in ServiceNow Frame
- September 2016
-
July 2016
- Jul 17, 2016 Granting Temporary Roles/Groups in ServiceNow
- Jul 15, 2016 Scripted REST APIs & Retrieving RITM Variables via SRAPI
-
May 2016
- May 17, 2016 What's New in Helsinki?
-
April 2016
- Apr 27, 2016 Customizing UI16 Through CSS and System Properties
- Apr 5, 2016 ServiceNow Versions: Express Vs. Enterprise
-
March 2016
- Mar 28, 2016 Update Set Collision Avoidance Tool: V2
- Mar 18, 2016 ServiceNow: What's New in Geneva & UI16 (Pt. 2)
-
February 2016
- Feb 22, 2016 Reference Field Auto-Complete Attributes
- Feb 6, 2016 GlideRecord & GlideAjax: Client-Side Vs. Server-Side
- Feb 1, 2016 Make Your Log Entries Easier to Find
-
January 2016
- Jan 29, 2016 A Better, One-Click Approval
- Jan 25, 2016 Quickly Move Changes Between Update Sets
- Jan 20, 2016 Customize the Reference Icon Pop-up
- Jan 7, 2016 ServiceNow: Geneva & UI16 - What's new
- Jan 4, 2016 Detect/Prevent Update Set Conflicts Before They Happen
-
December 2015
- Dec 28, 2015 SN101: Boolean logic and ServiceNow's Condition Builder
- Dec 17, 2015 Locate any record in any table, by sys_id in ServiceNow
- Dec 16, 2015 Detecting Duplicate Records with GlideAggregate
- Dec 11, 2015 Array.indexOf() not working in ServiceNow - Solution!
- Dec 2, 2015 Understanding Dynamic Filters & Checking a Record Against a Filter Using GlideFilter
- October 2015
-
August 2015
- Aug 27, 2015 Easily Clone One User's Access to Another User