Counting Records with `getRowCount`: A Comprehensive Guide






Mastering getRowCount() in ServiceNow: Your Go-To Guide for Counting Records Like a Pro


Mastering `getRowCount()` in ServiceNow: Your Go-To Guide for Counting Records Like a Pro

Alright, let’s talk numbers! In the vast, intricate world of ServiceNow, sometimes you just need to know how many. How many active incidents do we have? How many users are in a specific group? How many knowledge articles are pending review? The ability to accurately and efficiently count records is fundamental, not just for reporting, but for data validation, conditional logic in scripts, and even for performance optimization.

That’s where the trusty getRowCount() method comes into play. If you’ve spent any time scripting in ServiceNow, you’ve likely bumped into it. But like many simple-looking tools, there’s more to getRowCount() than meets the eye. It’s powerful, incredibly useful, but also comes with nuances and considerations you’ll want to master. Let’s dive deep and make sure you’re using it like a seasoned pro.

This article will guide you through the essentials, uncover practical applications, address common pitfalls, and even touch upon how knowing this method can make you shine in your next ServiceNow interview. Ready? Let’s get counting!

The Core Concept: Understanding getRowCount()

At its heart, getRowCount() is a method of the GlideRecord object in ServiceNow. Its sole purpose is to tell you how many records were found by your query. Simple, right? But the key is that it only works after you’ve executed your query. Think of it like this: you tell the database what you’re looking for, then you ask it, “So, how many did you find?”

What is GlideRecord? A Quick Refresher

Before we dive into getRowCount(), let’s quickly recap GlideRecord. It’s arguably the most fundamental API in ServiceNow scripting, allowing you to interact with the database. It lets you query, insert, update, and delete records from any table in your instance. Every time you want to get data out of a table, you’re probably starting with var gr = new GlideRecord('table_name');.

The Anatomy of a Basic Count

Let’s look at the most straightforward way to use getRowCount(), as demonstrated in our reference material:


var inc = new GlideRecord('incident');  
inc.query();  
gs.print(inc.getRowCount());  
    

Let’s break down each line:

  • var inc = new GlideRecord('incident');: This line creates a new GlideRecord object, specifically targeting the ‘incident’ table. It’s like telling ServiceNow, “Hey, I’m interested in incidents!”
  • inc.query();: This is the magic handshake with the database. Without any specific conditions (which we’ll add in a moment), this line tells ServiceNow to fetch *all* records from the ‘incident’ table. It executes the query and populates the GlideRecord object with the results. This step is crucial; getRowCount() will not work correctly without it.
  • gs.print(inc.getRowCount());: Finally, after the query has run, we ask our inc object, “How many records did you find?” The getRowCount() method returns an integer, which gs.print() then displays in the background script output, a UI Action info message, or a server-side log, depending on where your script runs.

Result: If you run this in a background script, you’ll see a single number printed, representing the total count of all incident records in your instance. Pretty neat, right?

Pro Tip: While gs.print() is traditional, modern ServiceNow scripting often favors gs.info(), gs.debug(), or gs.warn() for logging, as they offer better control over log levels and are visible in the System Logs application (syslog.do), making debugging easier in real-world scenarios.

Precision Counting: Filtering Your Results

Counting all records in a table is useful for auditing, but more often than not, you’ll need to count a specific subset of records. This is where filtering comes in, and getRowCount() works beautifully with it.

Using addQuery() for Targeted Counts

Our second reference example perfectly illustrates this:


var grUsers = new GlideRecord('sys_user');  
grUsers.addQuery('active', true); // or 'active=true' as a string  
grUsers.query();  
gs.print ('Active users are: ' + grUsers.getRowCount());  
    

Let’s break this down:

  • var grUsers = new GlideRecord('sys_user');: We’re now targeting the ‘sys_user’ table, which holds all user records.
  • grUsers.addQuery('active', true);: This is the filter! We’re telling ServiceNow, “Only consider users where the ‘active’ field is set to ‘true’.” addQuery() is super flexible. You can use it with two arguments (field name, value) or three (field name, operator, value), or even a single string like 'active=true'.
  • grUsers.query();: Again, we execute the query. Now, instead of fetching ALL users, it only fetches those matching our ‘active=true’ condition.
  • gs.print ('Active users are: ' + grUsers.getRowCount());: And finally, we get the count of only the active users.

Result: You’ll see something like “Active users are: [Number]” in your output, where [Number] is the count of active users in your instance.

Combining Multiple Filters

The real power of addQuery() (and its sibling addEncodedQuery()) shines when you need to layer multiple conditions. getRowCount() will count records that satisfy *all* your specified conditions (an implicit AND operator).

Imagine you want to count active users who also belong to a specific company:


var grActiveCompanyUsers = new GlideRecord('sys_user');
grActiveCompanyUsers.addQuery('active', true);
grActiveCompanyUsers.addQuery('company.name', 'ACME Corp'); // Assuming 'company' is a reference field to 'core_company'
grActiveCompanyUsers.query();
gs.print('Active users from ACME Corp: ' + grActiveCompanyUsers.getRowCount());
    

This script would give you a precise count of active users specifically associated with ‘ACME Corp’. See how quickly we can narrow down our focus?

Why getRowCount() is a Real-World Hero

Knowing how to use getRowCount() is one thing, but understanding when and why it’s invaluable is what truly elevates your ServiceNow game. It’s not just a fancy trick; it’s a fundamental building block for countless automation and data management tasks.

1. Dynamic Reporting and Dashboards

While ServiceNow’s out-of-the-box reporting is robust, sometimes you need a quick, script-driven metric for a custom dashboard widget or a server-side report generation. getRowCount() is perfect for this. You can easily create a script include that returns specific counts, which can then be displayed anywhere.


// Example: Script Include function to get critical open incidents
function getCriticalOpenIncidentCount() {
    var gr = new GlideRecord('incident');
    gr.addQuery('active', true);
    gr.addQuery('priority', 1); // Priority 1 = Critical
    gr.query();
    return gr.getRowCount();
}

// In a widget or business rule:
// var criticalCount = new MyUtils().getCriticalOpenIncidentCount();
// gs.info('Critical Open Incidents: ' + criticalCount);
    

2. Data Validation and Prevention

Imagine you have a requirement that there should never be more than one “Urgent” change request open at a time. Before creating a new “Urgent” change, you can use getRowCount() to check this condition.


// In a Before Insert/Update Business Rule on the Change Request table
if (current.priority == '1 - Critical' && current.state != '3 - Closed') { // Assuming 'Critical' is defined by priority 1
    var grCR = new GlideRecord('change_request');
    grCR.addQuery('priority', '1 - Critical');
    grCR.addQuery('state', '!=', '3 - Closed'); // Not closed, so still open or in progress
    grCR.addQuery('sys_id', '!=', current.sys_id); // Exclude the current change if it's an update
    grCR.query();

    if (grCR.getRowCount() > 0) {
        gs.addErrorMessage('Cannot create/update: Another Critical Change Request is already open.');
        current.setAbortAction(true);
    }
}
    

This is a powerful way to enforce business rules and maintain data integrity.

3. Conditional Logic in Workflows and Flows

While Flow Designer and Workflow activities often have their own ways to count (e.g., “Look Up Records” action with a count property), sometimes you need more granular control in a script step. You might want to branch a workflow based on whether a certain threshold of records is met.


// In a workflow script or Flow Designer script step
var highPriorityTasks = new GlideRecord('sc_task');
highPriorityTasks.addQuery('request_item', current.sys_id); // Tasks for the current RITM
highPriorityTasks.addQuery('priority', '1 - Critical');
highPriorityTasks.query();

if (highPriorityTasks.getRowCount() > 2) {
    // If more than 2 critical tasks, escalate to a manager
    gs.info('Too many critical tasks for RITM ' + current.number + '. Escalating!');
    // return 'escalate'; // For workflow branching
} else {
    // Proceed normally
    // return 'normal';
}
    

4. Troubleshooting and Debugging

Quickly verify if your query conditions are actually returning the data you expect. If you think your query should return 5 records but getRowCount() shows 0, you immediately know there’s an issue with your query parameters or the data itself.


// Debugging a complex query
var grProblem = new GlideRecord('problem');
grProblem.addEncodedQuery('active=true^priority=1^assignment_group=javascript:getMyGroups()');
grProblem.query();
gs.info('Problems found: ' + grProblem.getRowCount()); // Quick check to see if the query yields results
    

Advanced Scenarios and Best Practices: When to Use (and Not Use) getRowCount()

Okay, we’ve covered the basics and common use cases. Now let’s elevate our understanding. getRowCount() is fantastic, but like any powerful tool, it needs to be used wisely, especially when performance is a concern.

Performance Considerations: Small vs. Large Datasets

For small to moderately sized tables, or queries that return a limited number of results (tens, hundreds, maybe even a few thousand), getRowCount() is generally efficient. It makes a database call to fetch the record metadata (or the records themselves, depending on internal GlideRecord optimizations) and then provides the count.

However, when you’re dealing with very large tables (hundreds of thousands, millions of records) and your query is broad, using getRowCount() can become a performance bottleneck. Why? Because GlideRecord.query() fetches the actual records (or at least enough information to iterate through them) into memory on the application node before getRowCount() can determine the total. This can be resource-intensive.

Performance Warning: Avoid running getRowCount() on very broad queries against massive tables in highly transactional or performance-critical scripts (e.g., frequently triggered business rules, heavily used UI Actions) without careful consideration. It might lead to slow scripts or even instance performance degradation.

When to Consider Alternatives: Introducing GlideAggregate

For truly massive counts or when you need to group counts (e.g., “How many incidents per assignment group?”), GlideAggregate is your best friend. GlideAggregate is designed for database aggregation functions (COUNT, SUM, AVG, MIN, MAX) and performs these operations at the database level, often much more efficiently than GlideRecord, especially for large datasets. It avoids pulling all individual records into the application node’s memory.


// Using GlideAggregate to count incidents
var ga = new GlideAggregate('incident');
ga.addAggregate('COUNT'); // We want to count
ga.query(); // Execute the query
var incidentCount = 0;
if (ga.next()) {
    incidentCount = ga.getAggregate('COUNT');
}
gs.info('Total incidents (via GlideAggregate): ' + incidentCount);

// To get grouped counts, e.g., incidents per state:
var gaState = new GlideAggregate('incident');
gaState.addAggregate('COUNT', 'state'); // Count by state
gaState.groupBy('state'); // Group the results by state
gaState.query();
while (gaState.next()) {
    var stateName = gaState.state.getDisplayValue();
    var count = gaState.getAggregate('COUNT', 'state');
    gs.info('Incidents in state "' + stateName + '": ' + count);
}
    

Key takeaway: If you just need a simple count of records matching specific criteria, and the dataset isn’t astronomically huge, getRowCount() is perfectly fine. If you’re dealing with millions of records or need aggregated data (sums, averages, grouped counts), lean towards GlideAggregate for better performance.

The Interaction with setLimit()

GlideRecord.setLimit(n) restricts the number of records returned by a query. If you use setLimit() before query(), getRowCount() will return the number of records up to that limit, not the total number of matching records in the database.


var grLimited = new GlideRecord('incident');
grLimited.addQuery('active', true);
grLimited.setLimit(5); // Only fetch a maximum of 5 active incidents
grLimited.query();
gs.info('Limited count of active incidents: ' + grLimited.getRowCount());
// If there are 100 active incidents, this will print '5'.
// If there are only 3 active incidents, this will print '3'.
    

This is important to remember. If you need the *actual total count* regardless of how many records you want to process, do not use setLimit() before getRowCount().

What About an Empty Query?

If your addQuery() conditions don’t match any records, getRowCount() will gracefully return 0. This is exactly what you’d expect and is often used in conditional logic: if (gr.getRowCount() > 0) { // Do something }.

Troubleshooting getRowCount() Issues: When Things Go Sideways

Even though getRowCount() seems straightforward, you’ll inevitably run into situations where it doesn’t give you the results you expect. Don’t worry, that’s part of the learning process! Here are some common troubleshooting scenarios:

1. Getting 0 or -1 Unexpectedly

  • Incorrect Query Conditions: This is by far the most common culprit. Double-check your addQuery() statements. Are the field names correct? Is the operator right (e.g., != instead of =)? Is the value you’re searching for accurate (case sensitivity, exact match for strings, correct sys_id for references)?
    
    // Common mistake: Typo in field name
    var gr = new GlideRecord('incident');
    gr.addQuery('activee', true); // 'activee' instead of 'active'
    gr.query();
    gs.info(gr.getRowCount()); // Will likely print 0
    
    // Common mistake: Incorrect value for reference field
    var gr = new GlideRecord('incident');
    gr.addQuery('assigned_to', 'admin'); // Should be sys_id, not display value by default
    gr.query();
    gs.info(gr.getRowCount()); // Will likely print 0
                
  • Running getRowCount() Before query(): If you forget to call gr.query(), getRowCount() will return -1 (in older versions) or 0 (in newer versions/contexts), as no query has been executed yet to populate the record set. Always ensure query() precedes getRowCount().
  • ACLs (Access Control Lists): The script might be running in a context where the user (or the system) doesn’t have permission to read the records you’re trying to count. If an ACL prevents read access, those records effectively don’t exist for the query.
  • Table Name Typos: A simple mistake like sys_user vs. sys_users can lead to zero results.
  • Scope Issues: If you’re working in a custom application scope, ensure your script has access to the tables you’re querying, or use cross-scope access properly.

2. Performance Lag or Timeouts

  • Querying Huge Tables Without Filters: As discussed, `gr.query()` against a table with millions of records without any `addQuery()` conditions can try to pull everything, leading to slow performance or even transaction timeouts. Always try to limit your queries.
  • Complex or Unindexed Queries: If your query involves multiple `addQuery()` calls on fields that aren’t indexed in the database, it can force a full table scan, which is very slow. While you typically don’t control indexing directly in ServiceNow (SaaS), be aware that complex queries on non-indexed fields are performance killers.
  • Looping with `getRowCount()`: Avoid calling `getRowCount()` inside a `while (gr.next())` loop. It’s meant to be called once after `query()`.

3. Unexpected Higher Count

  • Missing addQuery(): You forgot a condition, so it’s counting more records than you intended. For example, you wanted to count active incidents, but forgot to add gr.addQuery('active', true);.
  • Incorrect Condition Logic: Perhaps you used an OR condition when you meant an AND, or a != operator when you meant =.

Debugging Tip: When troubleshooting, always print your query string using gr.getEncodedQuery() before running gr.query() and compare it to what you expect. You can also temporarily add gs.info(gr.getRowCount()); at various stages of your script to isolate where the count is going wrong.

Interview Relevance: Shining with getRowCount() Knowledge

If you’re interviewing for a ServiceNow developer, administrator, or consultant role, expect questions that touch upon fundamental scripting concepts like GlideRecord and database interaction. getRowCount() is a prime candidate for demonstrating your practical scripting knowledge and understanding of best practices.

Common Interview Questions & Expected Responses:

  1. “How would you count the number of active incidents in a script?”

    • Expected Answer: “I’d use a GlideRecord on the incident table, add a query for active=true, run the query, and then use the getRowCount() method. For example:”
      
      var grInc = new GlideRecord('incident');
      grInc.addQuery('active', true);
      grInc.query();
      var activeCount = grInc.getRowCount();
      gs.info('Active Incidents: ' + activeCount);
                          
  2. “What’s the difference between GlideRecord.getRowCount() and GlideAggregate.getRowCount() (or using GlideAggregate for counts)?”

    • Expected Answer:GlideRecord.getRowCount() is great for getting a count of records returned by a standard GlideRecord query, especially for smaller to medium datasets. However, for very large datasets or when needing to perform aggregate functions like counting, summing, or grouping on the database level, GlideAggregate is generally more performant. GlideAggregate processes the count on the database server itself, reducing the amount of data transferred to the application node.”
  3. “When would you not recommend using getRowCount()?”

    • Expected Answer: “I’d be cautious using getRowCount() in performance-critical scripts against extremely large tables without very specific filters, as it can be resource-intensive. In such cases, GlideAggregate would be my preferred method. Also, if I only need to check if *any* records exist, I might use gr.next() immediately after gr.query() and then gr.hasNext(), as that might be slightly more efficient if I don’t need the exact number, just presence.”
  4. “What happens if you call getRowCount() before query()?”

    • Expected Answer: “It won’t work correctly. It will typically return 0 or -1 because no query has been executed to populate the record set yet. The query() method is essential to fetch the data first.”

By articulating these points, you’re not just showing you know the syntax, but that you understand the underlying mechanisms, performance implications, and best practices – which is exactly what employers are looking for.

Wrapping It Up: Count with Confidence!

So there you have it – a comprehensive tour of getRowCount() in ServiceNow. From its basic usage to advanced considerations, troubleshooting, and interview relevance, you’re now equipped to wield this method with confidence and precision. It’s a testament to the fact that even seemingly simple functions can hold a wealth of depth and practical application in the right context.

Remember, mastering ServiceNow scripting isn’t just about memorizing APIs; it’s about understanding how they interact with the platform, the database, and how they impact performance and user experience. getRowCount() is a fantastic example of a tool that, when understood deeply, can significantly enhance your ability to build robust, efficient, and intelligent solutions.

Keep experimenting, keep learning, and keep counting! Your ServiceNow journey is an exciting one, and every method you master brings you closer to becoming a true platform expert.


Scroll to Top