What is an encoded query?
An encoded query is a string that represents one or more filter conditions on a ServiceNow table. You have already seen them — they appear in the URL when you filter a list view. If you filter the Incident list to show only active P1 incidents assigned to a specific group, then look at the URL, you will see something like:
active=true^priority=1^assignment_group=GROUP_SYS_ID
That same string can be passed directly to GlideRecord using addEncodedQuery():
var gr = new GlideRecord('incident');
gr.addEncodedQuery('active=true^priority=1^assignment_group=GROUP_SYS_ID');
gr.query();
while (gr.next()) {
gs.log(gr.number + ' - ' + gr.short_description);
}
The encoded query is translated directly to a SQL WHERE clause. It is not interpreted by JavaScript — it goes straight to the database engine, which is why it performs well.
The fastest way to build encoded queries
Never write complex encoded queries by hand when the list view will build them for you:
- Navigate to the table you are working with (e.g., go to the Incident list)
- Add filters using the funnel icon or right-click filtering until you have exactly the conditions you want
- Right-click the breadcrumb at the top of the filter (the row showing your conditions)
- Select Copy query
- Paste the result directly into your script
The platform builds the correctly formatted encoded query string for any conditions you can express in the UI — including complex OR logic, date ranges, and reference field conditions. This is faster than writing syntax by hand and eliminates errors.
AND conditions — the ^ separator
Conditions joined with ^ are AND conditions — all must be true for a record to match:
// active = true AND state = 1 AND priority IN (1, 2)
gr.addEncodedQuery('active=true^state=1^priorityIN1,2');
OR conditions — the ^OR separator
Conditions joined with ^OR are OR conditions — any one must be true:
// state = 1 OR state = 2 OR state = 3
gr.addEncodedQuery('state=1^ORstate=2^ORstate=3');
// Equivalent using IN operator (simpler):
gr.addEncodedQuery('stateIN1,2,3');
Combining AND and OR requires careful thought about operator precedence. In ServiceNow encoded queries, conditions are evaluated left-to-right with no explicit grouping — the system alternates between AND blocks and OR blocks. For complex OR logic with multiple AND conditions, test carefully in the list view first:
// active=true AND (category=hardware OR category=software)
// Built from the UI — this is the exact string ServiceNow generates:
gr.addEncodedQuery('active=true^categoryINhardware,software');
// active=true AND (state=1 OR (state=2 AND priority=1))
// Complex — build in list view to get the exact string
The NQ operator — OR between groups
NQ (New Query) creates a separate OR condition block. It is the encoded query equivalent of the NQ condition in the Advanced filter. Use it when you need two completely separate condition sets joined by OR:
// (active=true AND priority=1) OR (state=3 AND category=hardware)
gr.addEncodedQuery('active=true^priority=1^NQstate=3^category=hardware');
NQ is uncommon but important to know when you encounter it in copied query strings.
Complete operator reference
Equality and inequality
// Equals
gr.addEncodedQuery('state=1');
// Not equals
gr.addEncodedQuery('state!=6');
// Greater than / less than
gr.addEncodedQuery('priority<3'); // priority is less than 3
gr.addEncodedQuery('priority>1'); // priority is greater than 1
gr.addEncodedQuery('priority>=2'); // priority is >= 2
gr.addEncodedQuery('priority<=3'); // priority is <= 3
IN and NOT IN
// Value is in a comma-separated list
gr.addEncodedQuery('stateIN1,2,3'); // state is 1, 2, or 3
gr.addEncodedQuery('priorityIN1,2'); // P1 or P2
// Value is not in a list
gr.addEncodedQuery('stateNOT IN6,7,8'); // state is not 6, 7, or 8
// For reference fields — sys_ids in the list
gr.addEncodedQuery('assignment_groupIN' + groupSysId1 + ',' + groupSysId2);
String operators
// Starts with
gr.addEncodedQuery('numberSTARTSWITHINC'); // incidents only (vs CHG, RITM etc.)
// Ends with
gr.addEncodedQuery('short_descriptionENDSWITHurgent');
// Contains (case-insensitive substring match)
gr.addEncodedQuery('short_descriptionCONTAINSnetwork');
// Does not contain
gr.addEncodedQuery('short_descriptionDOES NOT CONTAINtest');
// LIKE (similar to CONTAINS but supports wildcards with %)
gr.addEncodedQuery('short_descriptionLIKEnetwork%outage');
Empty and not empty
// Field has no value
gr.addEncodedQuery('assignment_groupISEMPTY'); // no group assigned
gr.addEncodedQuery('close_notesISEMPTY');
// Field has a value
gr.addEncodedQuery('assignment_groupISNOTEMPTY'); // has a group
gr.addEncodedQuery('resolved_atISNOTEMPTY'); // has been resolved
BETWEEN
// Numeric range
gr.addEncodedQuery('priorityBETWEEN1@2'); // priority between 1 and 2 (inclusive)
// Date range — use JavaScript date functions
gr.addEncodedQuery('opened_atBETWEENjavascript:gs.daysAgoStart(30)@javascript:gs.daysAgoEnd(0)');
INSTANCEOF — filter by table hierarchy
// Return only direct instances of task that are incidents
// (vs all task subtypes)
gr.addEncodedQuery('sys_class_nameINSTANCEOFincident');
Date and time operators
ServiceNow provides relative date operators that use JavaScript date functions embedded in the encoded query. These are especially useful in Scheduled Jobs and reports:
// ON operator — records where date falls in a period
// (using the JavaScript date function syntax)
gr.addEncodedQuery('opened_atONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()');
gr.addEncodedQuery('opened_atONThis week@javascript:gs.beginningOfThisWeek()@javascript:gs.endOfThisWeek()');
gr.addEncodedQuery('opened_atONThis month@javascript:gs.beginningOfThisMonth()@javascript:gs.endOfThisMonth()');
gr.addEncodedQuery('opened_atONLast month@javascript:gs.beginningOfLastMonth()@javascript:gs.endOfLastMonth()');
gr.addEncodedQuery('opened_atONThis quarter@javascript:gs.beginningOfThisQuarter()@javascript:gs.endOfThisQuarter()');
// Relative date comparison
gr.addEncodedQuery('opened_at>=javascript:gs.daysAgoStart(7)'); // last 7 days
gr.addEncodedQuery('sys_created_on>=javascript:gs.daysAgoStart(30)');
// Exact date comparison
gr.addEncodedQuery('opened_at>=2026-01-01 00:00:00^opened_at<2026-02-01 00:00:00');
Build date queries using the list view to get the exact format ServiceNow expects — date encoding can vary by timezone and instance configuration.
Reference field conditions
Reference fields store sys_ids. When you filter on a reference field, use the sys_id as the value:
// Filter by assignment_group sys_id
gr.addEncodedQuery('assignment_group=6816f79cc0a8016401c5a33be04be441');
// Filter by current user
gr.addEncodedQuery('assigned_to=' + gs.getUserID());
// Filter by multiple groups
gr.addEncodedQuery('assignment_groupIN' + groupId1 + ',' + groupId2);
Filtering by display value on a reference field
If you only have the display value (name) of a referenced record rather than its sys_id, use dot-walking to filter on the related record's field:
// Filter incidents where assignment group name contains "Network"
gr.addEncodedQuery('assignment_group.nameLIKENetwork');
// Filter by the department of the assigned user
gr.addEncodedQuery('assigned_to.department.nameSTARTSWITHIT');
// Filter by location name
gr.addEncodedQuery('location.nameCONTAINSLondon');
Dot-walking in queries works up to several levels deep, but be aware that each level of dot-walking adds a JOIN in the underlying SQL query. Deep dot-walking on large tables can be slow if the referenced tables are also large.
Combining addEncodedQuery with addQuery
You can combine addEncodedQuery() with addQuery() in the same GlideRecord — they are both AND conditions applied to the same query:
var gr = new GlideRecord('incident');
gr.addEncodedQuery('active=true^priorityIN1,2'); // base conditions
gr.addQuery('assignment_group', groupSysId); // additional condition
gr.addQuery('state', '!=', '6'); // field, operator, value
gr.orderBy('priority');
gr.setLimit(50);
gr.query();
There is no functional difference — both produce SQL AND conditions. Use whichever is clearer for a given situation. Complex conditions built from the UI are easier to read as encoded query strings; simple programmatic conditions (like using a variable value) are often cleaner as addQuery() calls.
addQuery() operator syntax
When using addQuery() rather than encoded queries, operators are specified as the second of three arguments:
// Two-argument form — implicit equals
gr.addQuery('state', '1');
// Three-argument form — explicit operator
gr.addQuery('state', '!=', '6'); // not equals
gr.addQuery('priority', '<=', '2'); // less than or equal
gr.addQuery('short_description', 'CONTAINS', 'network');
gr.addQuery('assignment_group', 'ISNOTEMPTY', '');
gr.addQuery('state', 'IN', '1,2,3');
gr.addQuery('opened_at', '>=', gs.daysAgoStart(7));
Encoded queries in GlideAggregate
GlideAggregate uses the same encoded query syntax as GlideRecord — addEncodedQuery() and addQuery() work identically:
var ga = new GlideAggregate('incident');
ga.addEncodedQuery('active=true^priorityIN1,2^stateNOT IN6,7');
ga.addAggregate('COUNT', 'priority');
ga.groupBy('priority');
ga.query();
while (ga.next()) {
gs.log('P' + ga.getValue('priority') + ': ' + ga.getAggregate('COUNT', 'priority'));
}
For the complete GlideAggregate reference, see the GlideAggregate guide.
Common mistakes
Mistake 1 — Confusing AND and OR separator syntax
// AND — uses ^
gr.addEncodedQuery('active=true^priority=1'); // active AND priority=1
// OR — uses ^OR
gr.addEncodedQuery('state=1^ORstate=2'); // state=1 OR state=2
// Common mistake — using ^ where ^OR was intended
gr.addEncodedQuery('state=1^state=2'); // Wrong — state cannot be both 1 AND 2 simultaneously
Mistake 2 — Using display values instead of sys_ids for reference fields
// Wrong — 'Service Desk' is the display value, not the sys_id
gr.addEncodedQuery('assignment_group=Service Desk');
// Right — use the sys_id
gr.addEncodedQuery('assignment_group=SYS_ID_OF_SERVICE_DESK_GROUP');
// Or use dot-walking on the name field
gr.addEncodedQuery('assignment_group.name=Service Desk'); // Exact match on name
Mistake 3 — Building complex OR logic incorrectly
OR logic in encoded queries has specific precedence rules that differ from most programming languages. When you need complex AND+OR combinations, always build the query in the list view first and copy the result — do not try to construct it manually.
Mistake 4 — Using hardcoded dates
// Bad — hardcoded date, script becomes stale
gr.addEncodedQuery('opened_at>=2026-01-01 00:00:00');
// Good — relative date, always works correctly
gr.addEncodedQuery('opened_at>=javascript:gs.beginningOfThisYear()');
Debugging encoded queries
If an encoded query is not returning the records you expect:
- Copy the query string and paste it directly into the list view filter breadcrumb — it should show the conditions correctly
- Run the query in Scripts - Background and log the results with gs.log() to see what is actually returned
- Check that reference field values are sys_ids, not display values
- Check date formatting — dates in encoded queries must match the instance timezone and format settings
For more debugging techniques, see the complete debugging guide.
Related guides
- GlideAggregate guide — same query syntax applied to aggregate functions
- GlideRecord performance tips — using queries efficiently on large tables
- Debugging ServiceNow scripts — testing and validating query results
- Script Includes guide — building reusable query methods