- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
I am trying to understand exactly how _queryMatch works in the Lookup Rules. There is very little information other than the start of the default scripts.
// _queryMatch function checks if the query returns 0, 1 or more than 1 CI. // it returns: // null: if no CI found // ci record: if a unique CI was found // the first CI record found: if more than 1 CI was found and log a duplicate error message
If more than one CI is found it says it returns the first one. But there is no indication if it filters out CI's that are retired or non-operational, or try to get the one with the latest discovery date. And the default scripts do not take those into account in the GlideRecord queries.
I have in my notes that the Lookup Rules will return the CI with the latest created date, but I cannot recall if I saw that in some ServiceNow docs or one of their videos. So, I am not sure if the _queryMatch does anything with that. Any help will be appreciated. I will most likely just add those filters to the GlideRecord query so I can know what I am getting. But, if I do that, what is the purpose of _queryMatch?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
Core Behavior:
The _queryMatch function returns "the first CI record found" when multiple CIs match - it does NOT apply any intelligent filtering for operational status, discovery dates, or creation dates by default.
// Simple CI Lookup Rule Example - Hostname matching with proper filtering
(function process(rule, sourceValue, sourcePayload) {
var sourceField = {};
sourceField[rule.source_field] = sourceValue;
// Query for CI by hostname
var cmdbci = new GlideRecord("cmdb_ci_server");
cmdbci.addQuery("host_name", sourceValue);
// ADD YOUR FILTERS (what _queryMatch doesn't do)
cmdbci.addQuery('operational_status', '1'); // Operational only
cmdbci.addQuery('install_status', '!=', '7'); // Not retired
cmdbci.addQuery('duplicate_of', ''); // Not a duplicate
// Order by latest discovery date
cmdbci.orderByDesc('last_discovered');
cmdbci.query();
// Use _queryMatch for logging and duplicate handling
cmdbci = _queryMatch(cmdbci, rule, sourceField);
if (cmdbci) {
return cmdbci.getUniqueValue();
}
return null;
})(rule, sourceValue, sourcePayload);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
Core Behavior:
The _queryMatch function returns "the first CI record found" when multiple CIs match - it does NOT apply any intelligent filtering for operational status, discovery dates, or creation dates by default.
// Simple CI Lookup Rule Example - Hostname matching with proper filtering
(function process(rule, sourceValue, sourcePayload) {
var sourceField = {};
sourceField[rule.source_field] = sourceValue;
// Query for CI by hostname
var cmdbci = new GlideRecord("cmdb_ci_server");
cmdbci.addQuery("host_name", sourceValue);
// ADD YOUR FILTERS (what _queryMatch doesn't do)
cmdbci.addQuery('operational_status', '1'); // Operational only
cmdbci.addQuery('install_status', '!=', '7'); // Not retired
cmdbci.addQuery('duplicate_of', ''); // Not a duplicate
// Order by latest discovery date
cmdbci.orderByDesc('last_discovered');
cmdbci.query();
// Use _queryMatch for logging and duplicate handling
cmdbci = _queryMatch(cmdbci, rule, sourceField);
if (cmdbci) {
return cmdbci.getUniqueValue();
}
return null;
})(rule, sourceValue, sourcePayload);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Thanks for the information. I typically do what you posted above just to be sure. However, it just bugged me not knowing exactly what it was meant for. Thanks for clarifying.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Glad I could help! If this solved your issue, please mark it as ✅ Helpful and ✅ Accept as Solution so others can benefit too.
Chavan A.P. Technical Architect | Certified Professional
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a week ago - last edited a week ago
So, I ran into another issue that now makes me question if _queryMatch does take into account Retired records or if there is something else going on.
I removed all my query lines for operational_status, install_status and duplicate_of (see code below)
I reapplied the lookup rules to a specific Discovered Item where it's CI record is Operational Status = Retired and Install Status = Retired. I would think the Lookup Rule would pick the Retired CI now that I am not filtering them out. However, what happened is the Lookup Rules failed to match and it was matched by IRE to the Retired CI. It also set the Op Status to Operational.
Next, I created a matrix to go through all the different Ops Status and Install Status options. After a while I noticed a pattern and stopped because it was taking a long time. I made it through all Operational Status options with Install Status of Installed, Absent, In Maintenance and In Stock before stopping. All were same outcome as below where only Operational Status = Retired and/or Install Status = Retired caused the CI Lookup rules to not match and it went to the IRE even though I was not filtering on those in my script. Operational Status = Non-Operational did not seem to have any effect as long as Install Status was not retired. Meaning Operational Status = Non-Operational and Install Status = Absent did Match by CI Lookup rules (also in matrix below).
Operational Status | Install Status | Outcome |
Operational | Installed | Matched by CI Lookup rules |
Non-Operational | Installed | Matched by CI Lookup rules |
Repair in Progress | Installed | Matched by CI Lookup rules |
DR Standby | Installed | Matched by CI Lookup rules |
Ready | Installed | Matched by CI Lookup rules |
Retired | Installed | Matched by IRE |
Operational | Absent | Matched by CI Lookup rules |
Non-Operational | Absent | Matched by CI Lookup rules |
Repair in Progress | Absent | Matched by CI Lookup rules |
DR Standby | Absent | Matched by CI Lookup rules |
Ready | Absent | Matched by CI Lookup rules |
Retired | Absent | Matched by IRE |
Operational | Retired | Matched by IRE |
Ready | Retired | Matched by IRE |
So, it seems having the queries for retired and non-op in the script does not matter. Either there is some setting I am not aware of, or _queryMatch does take into account the Op Status and Install Status.
// _queryMatch function checks if the query returns 0, 1 or more than 1 CI.
// it returns:
// null: if no CI found
// ci record: if a unique CI was found
// the first CI record found: if more than 1 CI was found and log a duplicate error message
// To avoid specific CI classes ,add the class names, comma separated, to the property sn_sec_cmn.ignoreCIClass
(function process(rule, sourceValue, sourcePayload) {
var sourceField = {};
var ignore = global.SecProperty.getProperty("sn_sec_cmn.ignoreCIClass", "");
sourceField[rule.source_field] = sourceValue;
var cmdbci = new GlideRecord("cmdb_ci");
cmdbci.addQuery("fqdn", sourceValue);
// Order by latest discovered date
cmdbci.orderByDesc('last_discovered');
if (!gs.nil(ignore))
cmdbci.addQuery('sys_class_name','NOT IN', ignore);
cmdbci.query();
cmdbci = _queryMatch(cmdbci, rule, sourceField);
if (cmdbci)
return cmdbci.getUniqueValue();
return null;
})(rule, sourceValue, sourcePayload);