<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Feature Tests on SNow adventures</title>
    <link>https://www.snow-adventures.com/categories/feature-tests/</link>
    <description>Recent content in Feature Tests on SNow adventures</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>© Samuel Meylan - 2020</copyright>
    <lastBuildDate>Tue, 18 Feb 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://www.snow-adventures.com/categories/feature-tests/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>jsonPath in ServiceNow with GlideJsonPath</title>
      <link>https://www.snow-adventures.com/posts/jsonpath-in-servicenow-with-glidejsonpath/</link>
      <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.snow-adventures.com/posts/jsonpath-in-servicenow-with-glidejsonpath/</guid>
      <description>This article explain how the JsonPath is supported in ServiceNow and how to use it with GlideJsonPath </description>
      <content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>
<p>Since the Vancouver release, there is a new API <code>GlideJsonPath</code><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> that allows to query a JSON string with <em>jsonPath</em><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<p>The <em>jsonPath</em> can be viewed as the JSON equivalent of the XPath for XML. It allows to perform queries like <code>$.library.bools.*.title</code> for example. <em>Jsonpath</em> is offically a RFC since february 2024<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
<p>I suspect the under the hood, it use the implementation JsonPath<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</p>
<h1 id="usage-of-the--glidejsonpath">Usage of the  <code>GlideJsonPath</code></h1>
<p>The official documentation<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> is very succint and there is a couple of extra information that can help:</p>
<ul>
<li>the <code>GlideJsonPath</code> expect a <em>String</em>, not an object as parameter</li>
<li>the <code>read</code> function seems to return an <em>array</em> of <em>JavaObject</em>, which are not the same as the javascript objects. It might need some kind of converstion before being able to use it.</li>
</ul>
<p>To ease the usage, I suggest to use a function like this one, that accept an Object as parameter and return also a <strong>javascript</strong> Object:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">	@name executeJSONpath
</span></span></span><span class="line"><span class="cl"><span class="cm">	@description execute the JSON path on the given object and return the result 
</span></span></span><span class="line"><span class="cl"><span class="cm">	@param {Object} [obj] - Object on which to execute the json path
</span></span></span><span class="line"><span class="cl"><span class="cm">	@param {String} [jsonPath] - Json path to use for the query
</span></span></span><span class="line"><span class="cl"><span class="cm">	@return {Object} Object after applying the jsonPath read
</span></span></span><span class="line"><span class="cl"><span class="cm">*/</span>
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">executeJSONpath</span> <span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">path</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">  <span class="k">try</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Convert the object to a JSON string
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">var</span> <span class="nx">jsonString</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">obj</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// call and retrieve the result from GlideJsonPath
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">var</span> <span class="nx">gjp</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideJsonPath</span><span class="p">(</span><span class="nx">jsonString</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">gjpResult</span> <span class="o">=</span> <span class="nx">gjp</span><span class="p">.</span><span class="nx">read</span><span class="p">(</span><span class="nx">path</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">gjpResult</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">exception</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s2">&#34;Error in function &#39;executeJSONpath&#39; : &#34;</span> <span class="o">+</span> <span class="nx">exception</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">exception</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="json-path-syntax">JSON path syntax</h2>
<p>The JSON path syntax can be summarized as follow:</p>
<h2 id="dot-notation-or-bracket-notation">dot-notation or bracket-notation</h2>
<p>the JsonPath can use either a dot-notation, like <code>$.store.book[0].title</code> or a bracker-notation <code>$['store']['book'][0]['title']</code></p>
<p>It can also use a mix of both, like this example: <code>$['store']['book'][0].title</code></p>
<p>Also in the bracket notation, it is possibe to specify mutliple attribute to retrieve, for example: `$[&lsquo;store&rsquo;][&lsquo;book&rsquo;][0].[&ldquo;title&rdquo;, &ldquo;author&rdquo;]</p>
<h2 id="elements">Elements</h2>
<p>The JsonPath can use the following elements <sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup><sup id="fnref1:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup><sup id="fnref1:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>:</p>
<ul>
<li><code>$</code>: The root element to query. This starts all path expressions.</li>
<li><code>@</code>: The current node being processed by a filter predicate.</li>
<li><code>*</code>: Wildcard. Available anywhere a name or numeric are required.</li>
<li><code>..</code>: Deep scan. Available anywhere a name is required.</li>
<li><code>.&lt;name&gt;</code>: Dot-notated child</li>
<li><code>['&lt;name&gt;' (, '&lt;name&gt;')]</code>: Bracket-notated child or children</li>
<li><code>[&lt;number&gt; (, &lt;number&gt;)]</code>: Array index or indexes</li>
<li><code>[start:end]</code>: Array slice operator</li>
<li><code>[?(&lt;expression&gt;)]</code>: Filter expression. Expression must evaluate to a boolean value.</li>
</ul>
<h2 id="functions">Functions</h2>
<p>The specification gives several functions (<code>min()</code>, <code>max()</code>, &hellip;), but unfortunately it seems thay are not supported by the ServiceNow implementation.</p>
<h2 id="operators">Operators</h2>
<p>For use in the expression, we can use the &ldquo;classic&rdquo; operator like &ldquo;==&rdquo;, &ldquo;!=&rdquo;, &ldquo;&gt;&rdquo;, &ldquo;=&gt;&rdquo;, etc. It also supports:</p>
<ul>
<li><code>=~</code>: left matches regular expression [?(@.name =~ /foo.*?/i)]</li>
<li><code>in</code>: left exists in right [?(@.size in [&lsquo;S&rsquo;, &lsquo;M&rsquo;])]</li>
<li><code>nin</code>: left does not exists in right</li>
<li><code>subsetof</code>: left is a subset of right [?(@.sizes subsetof [&lsquo;S&rsquo;, &lsquo;M&rsquo;, &lsquo;L&rsquo;])]</li>
<li><code>anyof</code>: left has an intersection with right [?(@.sizes anyof [&lsquo;M&rsquo;, &lsquo;L&rsquo;])]</li>
<li><code>noneof</code>: left has no intersection with right [?(@.sizes noneof [&lsquo;M&rsquo;, &lsquo;L&rsquo;])]</li>
<li><code>size</code>: size of left (array or string) should match right</li>
<li><code>empty</code>: left (array or string) should be empty</li>
</ul>
<h2 id="limitations">Limitations</h2>
<ul>
<li><strong>functions</strong>: functions are not supported, as stated above</li>
<li><strong>unique values</strong>: There is not way to ask for unique values: there can be duplicated entries (for example when listing all categories)</li>
</ul>
<h1 id="example-of-json-path">Example of JSON path</h1>
<p>This table show the result of various jsonPath from the GitHub JsonPath documentation<sup id="fnref2:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</p>
<p>When creating a new jsonPath, you can use this online evaluator<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> to test it</p>
<table>
  <thead>
      <tr>
          <th>Description</th>
          <th>JsonPath</th>
          <th>Result</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>The authors of all books</td>
          <td><code>$.store.book[*].author</code></td>
          <td>[</br> &ldquo;Nigel Rees&rdquo;,</br> &ldquo;Evelyn Waugh&rdquo;,</br> &ldquo;Herman Melville&rdquo;,</br> &ldquo;J. R. R. Tolkien&rdquo;</br>]</td>
      </tr>
      <tr>
          <td>The authors and category of all books</td>
          <td><code>$.store.book[*].[&lsquo;author&rsquo;,&rsquo;title&rsquo;]</code></td>
          <td>[</br> {</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;</br> },</br> {</br>  &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;</br> },</br> {</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;</br> },</br> {</br>  &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;</br> }</br>]</td>
      </tr>
      <tr>
          <td>Title of first book, mixing dot and bracket</td>
          <td><code>$[&lsquo;store&rsquo;][&lsquo;book&rsquo;][0].title</code></td>
          <td>[</br> &ldquo;Sayings of the Century&rdquo;</br>]</td>
      </tr>
      <tr>
          <td>All authors</td>
          <td><code>$..author</code></td>
          <td>[</br> &ldquo;Nigel Rees&rdquo;,</br> &ldquo;Evelyn Waugh&rdquo;,</br> &ldquo;Herman Melville&rdquo;,</br> &ldquo;J. R. R. Tolkien&rdquo;</br>]</td>
      </tr>
      <tr>
          <td>All things, both books and bicycles</td>
          <td><code>$.store.*</code></td>
          <td>[</br> [</br>  {</br>   &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>   &ldquo;price&rdquo;: 8.95</br>  },</br>  {</br>   &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>   &ldquo;price&rdquo;: 12.99</br>  },</br>  {</br>   &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>   &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>   &ldquo;price&rdquo;: 8.99</br>  },</br>  {</br>   &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>   &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>   &ldquo;price&rdquo;: 22.99</br>  }</br> ],</br> {</br>  &ldquo;color&rdquo;: &ldquo;red&rdquo;,</br>  &ldquo;price&rdquo;: 19.95</br> }</br>]</td>
      </tr>
      <tr>
          <td>The price of everything</td>
          <td><code>$.store..price</code></td>
          <td>[</br> 8.95,</br> 12.99,</br> 8.99,</br> 22.99,</br> 19.95</br>]</td>
      </tr>
      <tr>
          <td>The third book</td>
          <td><code>$..book[2]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>The second to last book</td>
          <td><code>$..book[-2]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>The first two books</td>
          <td><code>$..book[0,1]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>  &ldquo;price&rdquo;: 8.95</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>  &ldquo;price&rdquo;: 12.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books from index 0 (inclusive) until index 2 (exclusive)</td>
          <td><code>$..book[:2]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>  &ldquo;price&rdquo;: 8.95</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>  &ldquo;price&rdquo;: 12.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books from index 1 (inclusive) until index 2 (exclusive)</td>
          <td><code>$..book[1:2]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>  &ldquo;price&rdquo;: 12.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>Last two books</td>
          <td><code>$..book[-2:]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>  &ldquo;price&rdquo;: 22.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books from index 2 (inclusive) to last</td>
          <td><code>$..book[2:]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>  &ldquo;price&rdquo;: 22.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books with an ISBN number</td>
          <td><code>$..book[?(@.isbn)]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>  &ldquo;price&rdquo;: 22.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books in store cheaper than 10</td>
          <td><code>$.store.book[?(@.price &lt; 10)]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>  &ldquo;price&rdquo;: 8.95</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books in store that are not &rsquo;expensive&rsquo;</td>
          <td><code>$..book[?(@.price &lt;= $[&rsquo;expensive&rsquo;])]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>  &ldquo;price&rdquo;: 8.95</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> }</br>]</td>
      </tr>
      <tr>
          <td>All books matching regex (ignore case)</td>
          <td><code>$..book[?(@.author =~ /.*REES/i)]</code></td>
          <td>[</br> {</br>  &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>  &ldquo;price&rdquo;: 8.95</br> }</br>]</td>
      </tr>
      <tr>
          <td>Give me everything</td>
          <td><code>$..*</code></td>
          <td>[</br> {</br>  &ldquo;book&rdquo;: [</br>   {</br>    &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>    &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>    &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>    &ldquo;price&rdquo;: 8.95</br>   },</br>   {</br>    &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>    &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>    &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>    &ldquo;price&rdquo;: 12.99</br>   },</br>   {</br>    &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>    &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>    &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>    &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>    &ldquo;price&rdquo;: 8.99</br>   },</br>   {</br>    &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>    &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>    &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>    &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>    &ldquo;price&rdquo;: 22.99</br>   }</br>  ],</br>  &ldquo;bicycle&rdquo;: {</br>   &ldquo;color&rdquo;: &ldquo;red&rdquo;,</br>   &ldquo;price&rdquo;: 19.95</br>  }</br> },</br> 10,</br> [</br>  {</br>   &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>   &ldquo;price&rdquo;: 8.95</br>  },</br>  {</br>   &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>   &ldquo;price&rdquo;: 12.99</br>  },</br>  {</br>   &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>   &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>   &ldquo;price&rdquo;: 8.99</br>  },</br>  {</br>   &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>   &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>   &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>   &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>   &ldquo;price&rdquo;: 22.99</br>  }</br> ],</br> {</br>  &ldquo;color&rdquo;: &ldquo;red&rdquo;,</br>  &ldquo;price&rdquo;: 19.95</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;reference&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Nigel Rees&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sayings of the Century&rdquo;,</br>  &ldquo;price&rdquo;: 8.95</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Evelyn Waugh&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Sword of Honour&rdquo;,</br>  &ldquo;price&rdquo;: 12.99</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;Herman Melville&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;Moby Dick&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-553-21311-3&rdquo;,</br>  &ldquo;price&rdquo;: 8.99</br> },</br> {</br>  &ldquo;category&rdquo;: &ldquo;fiction&rdquo;,</br>  &ldquo;author&rdquo;: &ldquo;J. R. R. Tolkien&rdquo;,</br>  &ldquo;title&rdquo;: &ldquo;The Lord of the Rings&rdquo;,</br>  &ldquo;isbn&rdquo;: &ldquo;0-395-19395-8&rdquo;,</br>  &ldquo;price&rdquo;: 22.99</br> },</br> &ldquo;reference&rdquo;,</br> &ldquo;Nigel Rees&rdquo;,</br> &ldquo;Sayings of the Century&rdquo;,</br> 8.95,</br> &ldquo;fiction&rdquo;,</br> &ldquo;Evelyn Waugh&rdquo;,</br> &ldquo;Sword of Honour&rdquo;,</br> 12.99,</br> &ldquo;fiction&rdquo;,</br> &ldquo;Herman Melville&rdquo;,</br> &ldquo;Moby Dick&rdquo;,</br> &ldquo;0-553-21311-3&rdquo;,</br> 8.99,</br> &ldquo;fiction&rdquo;,</br> &ldquo;J. R. R. Tolkien&rdquo;,</br> &ldquo;The Lord of the Rings&rdquo;,</br> &ldquo;0-395-19395-8&rdquo;,</br> 22.99,</br> &ldquo;red&rdquo;,</br> 19.95</br>]</td>
      </tr>
  </tbody>
</table>
<h2 id="sample-json">Sample JSON</h2>
<p>Here is the sample JSON used for the tests:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;store&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;book&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;category&#34;</span><span class="p">:</span> <span class="s2">&#34;reference&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;author&#34;</span><span class="p">:</span> <span class="s2">&#34;Nigel Rees&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Sayings of the Century&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;price&#34;</span><span class="p">:</span> <span class="mf">8.95</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;category&#34;</span><span class="p">:</span> <span class="s2">&#34;fiction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;author&#34;</span><span class="p">:</span> <span class="s2">&#34;Evelyn Waugh&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Sword of Honour&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;price&#34;</span><span class="p">:</span> <span class="mf">12.99</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;category&#34;</span><span class="p">:</span> <span class="s2">&#34;fiction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;author&#34;</span><span class="p">:</span> <span class="s2">&#34;Herman Melville&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Moby Dick&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;isbn&#34;</span><span class="p">:</span> <span class="s2">&#34;0-553-21311-3&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;price&#34;</span><span class="p">:</span> <span class="mf">8.99</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;category&#34;</span><span class="p">:</span> <span class="s2">&#34;fiction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;author&#34;</span><span class="p">:</span> <span class="s2">&#34;J. R. R. Tolkien&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;The Lord of the Rings&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;isbn&#34;</span><span class="p">:</span> <span class="s2">&#34;0-395-19395-8&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;price&#34;</span><span class="p">:</span> <span class="mf">22.99</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;bicycle&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;color&#34;</span><span class="p">:</span> <span class="s2">&#34;red&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;price&#34;</span><span class="p">:</span> <span class="mf">19.95</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;expensive&#34;</span><span class="p">:</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><hr>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://developer.servicenow.com/dev.do#!/reference/api/washingtondc/server_legacy/GlideJsonPathAPI#GlideJsonPath-GlideJsonPath_S?navFilter=jsonpath">GlideJsonPath | ServiceNow Developers</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://restfulapi.net/json-jsonpath/">JSON with JSONPath</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://datatracker.ietf.org/doc/rfc9535/">RFC 9535 - JSONPath: Query Expressions for JSON</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://github.com/json-path/JsonPath">GitHub - json-path/JsonPath: Java JsonPath implementation</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://jsonpath.com/">JSONPath Online Evaluator</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]></content:encoded>
    </item>
    
    <item>
      <title>Playing with the Transformation Service Plugin</title>
      <link>https://www.snow-adventures.com/posts/playing-with-the-transformation-service-plugin/</link>
      <pubDate>Fri, 26 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://www.snow-adventures.com/posts/playing-with-the-transformation-service-plugin/</guid>
      <description>Overview and usage of the Transformation Service Plugin</description>
      <content:encoded><![CDATA[<h1 id="transformation-service-plugin">Transformation Service Plugin</h1>
<p>The plugin &ldquo;Transformation Service Plugin&rdquo; provides a transfomer API that allows to process JSON or XML data by applying transformations and rules and returning a key/value object with the result.</p>
<p>We will see in this post how it work and what are the limitations and  go through a few examples.</p>
<p>Before going further, make sure that the plugin &ldquo;Transformation Service Plugin&rdquo; (<code>com.glide.transform</code>) is activated in your instance. If not activate it.</p>
<h1 id="overview-of-the-api">Overview of the API</h1>
<p>There are in fact 3 APIs designed to work together to achieve the transformation of the data.</p>
<p>The 3 APIs are:</p>
<ul>
<li><code>Transformer</code> API, that provide the necessary functions to perform the transformation and retrieve the results;</li>
<li><code>TransformerDefinition</code> API, that allows to define the transformation, using a set of rules and a path;</li>
<li><code>TransformerRuleList</code> API, used to defined the transform rules to apply.</li>
</ul>
<p>In a nutshell, you need to create all the transformation rules with <code>TransformerRuleList</code>, add the rules list to the  <code>TransformerDefinition</code> and use the this definition with <code>Transformer</code> to actually process and transform the data.</p>
<h1 id="test-case">Test case</h1>
<p>For this post, we will use data coming from the user table, via a REST api call.</p>
<p>For the sack of simplicity, we will connect to the same instance. The goal here is just to get the data in a JSON format and play with the transform functionnality.</p>
<p>If necessary, for the REST message creation, you can have a look to the post about <a href="/blog/2020-06-10-using-remote-tables-in-service-now/">Using Remote Tables in Service-Now</a>, as we are reusing the message here.</p>
<p>From now, we will aways use the following code to get the data with the subsequent examples:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">r</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_ws</span><span class="p">.</span><span class="nx">RESTMessageV2</span><span class="p">(</span><span class="s1">&#39;x_12270_remote_tab.my users&#39;</span><span class="p">,</span> <span class="s1">&#39;Get&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">response</span> <span class="o">=</span> <span class="nx">r</span><span class="p">.</span><span class="nx">execute</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">responseBody</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getBody</span><span class="p">();</span>
</span></span></code></pre></div><p>As a result, we get a JSON like this one, containig all the fields from the user table in the variable <code>responseBody</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-JSON" data-lang="JSON"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;result&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;calendar_integration&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;country&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;user_password&#34;</span><span class="p">:</span> <span class="s2">&#34;jF9fbZrY7c&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;last_login_time&#34;</span><span class="p">:</span> <span class="s2">&#34;2019-04-05 22:16:30&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;source&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="err">....</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">	<span class="err">.....</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h1 id="transformation-rules">Transformation rules</h1>
<p>The first step is to define the transformation rules.</p>
<p>In our scenario we will start with rules to :</p>
<ul>
<li>Concatenate the <code>first_name</code> and <code>last_name</code> and add a String &ldquo;User &quot; in front;</li>
<li>Replace the &ldquo;email&rdquo; user name by stars (&rdquo;***&quot;), but keep the domain part (&ldquo;<a href="mailto:user@domain.com">user@domain.com</a>&rdquo; becomes &ldquo;***@domain.com&rdquo;);</li>
<li>Define a &ldquo;type&rdquo;, that is either ACTIVE, INACTIVE, based on <code>active</code> field;</li>
<li>Use a few more fields as it</li>
</ul>
<p>This gives us the following code, wrapped in a function <code>getTransformerRuleList</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getTransformerRuleList</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">transformerRuleList</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_tfrm</span><span class="p">.</span><span class="nx">TransformerRuleList</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">fromJSON</span><span class="p">()</span> <span class="cm">/* indicate it is from JSON*/</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">setName</span><span class="p">(</span><span class="s1">&#39;Margin per users&#39;</span><span class="p">)</span> <span class="cm">/*name of the rule list*/</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* Rules for user concatenated name */</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="s1">&#39;$.first_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;last_name&#39;</span><span class="p">,</span> <span class="s1">&#39;$.last_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">thenConcat</span><span class="p">(</span><span class="s1">&#39;User &#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">thenConcatSymbol</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">thenConcat</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">thenConcatSymbol</span><span class="p">(</span><span class="s1">&#39;last_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* Rules for email */</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;$.email&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">thenSplit</span><span class="p">(</span><span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;***@$2&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* Rules for active field*/</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;$.active&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">thenApplyMap</span><span class="p">({</span><span class="s1">&#39;true&#39;</span><span class="o">:</span> <span class="s1">&#39;ACTIVE&#39;</span><span class="p">,</span> <span class="s1">&#39;false&#39;</span><span class="o">:</span><span class="s1">&#39;INACTIVE&#39;</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">transformerRuleList</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The <code>.fromJSON()</code> is here to indicate that we will parse a JSON source. We would use <code>.fromXML() </code>in case of an XML source.</p>
<p>Then the <code>.setName()</code>is used to give a name to the rule list.</p>
<p>For the rules themself, the logic is always to add a new rule with <code>.addRule()</code> where we give the resulting <em>name</em>  and then where the value is coming from in the source. For example <code>.addRule('first_name', '$.first_name')</code>.</p>
<p>After the <code>.addRule()</code>, we can add one or several <code>.thenSomething</code> method to further modify the value, like for example concatenate with <code>.thenConcat</code>, map with <code>.thenMap</code> and so on. You can find the full list in the API documentation.</p>
<h1 id="executing-the-transformation">executing the transformation</h1>
<p>Now that the rules are defined, we can create a <code>TransformerDefinition</code>and start the transformation with <code>Transformer</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Create a transformer definition and use the rule list and the record path 
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">path</span> <span class="o">=</span> <span class="s1">&#39;$.result.*&#39;</span><span class="p">;</span>  <span class="c1">// all the records in the JSON are below &#34;result&#34;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">transformerDefinition</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_tfrm</span><span class="p">.</span><span class="nx">TransformerDefinition</span><span class="p">(</span><span class="nx">getTransformerRuleList</span><span class="p">(),</span> <span class="nx">path</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">// Instantiate the transformer object.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">transformer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_tfrm</span><span class="p">.</span><span class="nx">Transformer</span><span class="p">(</span><span class="nx">transformerDefinition</span><span class="p">,</span> <span class="nx">responseBody</span><span class="p">);</span> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Transform all the records of the source, push them in array results and display the the row
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">results</span> <span class="o">=</span> <span class="p">[];</span> 
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span><span class="nx">transformer</span><span class="p">.</span><span class="nx">transform</span><span class="p">())</span> <span class="p">{</span> 
</span></span><span class="line"><span class="cl">  <span class="kd">var</span> <span class="nx">row</span> <span class="o">=</span> <span class="nx">transformer</span><span class="p">.</span><span class="nx">getRow</span><span class="p">()</span> 
</span></span><span class="line"><span class="cl">  <span class="nx">results</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">row</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">row</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> 
</span></span></code></pre></div><p><code>transform()</code>is executing the transaction for the next row and <code>getRow()</code> retrieve the row, in the form of an object with key-value pairs, as defined in the rule list.</p>
<h1 id="calculation-failure">Calculation failure</h1>
<p>I wanted to explore the calculation functions provided and see how it works. Unfortunatly I couldn&rsquo;t make them work when involving two differents elements from the source.</p>
<p>For example, in order to play with the calculations, I added some fields to the user table:</p>
<ul>
<li>Two currency fields
<ul>
<li><code>u_invoiced_price_per_hour</code></li>
<li><code>u_cost_per_hour</code></li>
</ul>
</li>
<li>and on integer field:
<ul>
<li><code>u_hours_by_day</code></li>
</ul>
</li>
</ul>
<p>Then I tried to calculate the margin price for a user by substracting the <code>u_cost_per_hour</code> from <code>u_invoiced_price_per_hour</code>.</p>
<p>According the documentation it can be achieved by adding the following code to the <code>getTransformerRuleList</code> function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="cm">/* Rules for margin */</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;margin&#39;</span><span class="p">,</span> <span class="s1">&#39;$.u_invoiced_price_per_hour&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nx">thenSubtract</span><span class="p">(</span><span class="s1">&#39;$.u_cost_per_hour&#39;</span><span class="p">);</span>
</span></span></code></pre></div><p>Unfortunatly it doesn&rsquo;t work and return errors like this one:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Evaluator: java.lang.NumberFormatException
</span></span><span class="line"><span class="cl">   Caused by error in script at line 21
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">     18: } 
</span></span><span class="line"><span class="cl">     19: 
</span></span><span class="line"><span class="cl">     20: function getTransformerRuleList () {
</span></span><span class="line"><span class="cl">==&gt;  21:     var transformerRuleList = new sn_tfrm.TransformerRuleList()
</span></span><span class="line"><span class="cl">     22:         .fromJSON() /* indicate it is from JSON*/
</span></span><span class="line"><span class="cl">     23:         .setName(&#39;Margin per users&#39;) /*name of the rule list*/
</span></span><span class="line"><span class="cl">     24:         /* Rules for user concatenated name */
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">java.math.BigDecimal.&lt;init&gt;(BigDecimal.java:497)
</span></span><span class="line"><span class="cl">java.math.BigDecimal.&lt;init&gt;(BigDecimal.java:827)
</span></span><span class="line"><span class="cl">com.glide.transform.adapter.CalculationAdapterRule.&lt;init&gt;(CalculationAdapterRule.java:222)
</span></span><span class="line"><span class="cl">com.glide.transform.adapter.CalculationAdapterRule.createMultiplicationAdapterRule(CalculationAdapterRule.java:60)
</span></span><span class="line"><span class="cl">com.glide.transform.transformer.AdapterRuleBuilder.thenSubtract(AdapterRuleBuilder.java:78)
</span></span><span class="line"><span class="cl">com.glide.transform.transformer.js.TransformerRuleList.jsFunction_thenSubtract(TransformerRuleList.java:85)
</span></span><span class="line"><span class="cl">sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
</span></span><span class="line"><span class="cl">sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
</span></span><span class="line"><span class="cl">sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
</span></span><span class="line"><span class="cl">java.lang.reflect.Method.invoke(Method.java:498)
</span></span><span class="line"><span class="cl">... 
</span></span></code></pre></div><p>I try various syntaxes, I try adding a <code>parseInt()</code>and so on, but I couldn&rsquo;t make it work.</p>
<p>The only way it work was to replace the <code>'$.u_cost_per_hour'</code> by a number, like in the code below, but this would not by useful in our case.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="cm">/* Rules for margin */</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nx">addRule</span><span class="p">(</span><span class="s1">&#39;margin&#39;</span><span class="p">,</span> <span class="s1">&#39;$.u_invoiced_price_per_hour&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nx">thenSubtract</span><span class="p">(</span><span class="mi">15</span><span class="p">);</span> <span class="cm">/*.thenSubtract(&#39;$.u_cost_per_hour&#39;);*/</span>
</span></span></code></pre></div><h1 id="alternative">Alternative</h1>
<p>Bases on this tests, I have the feeling that simply parsing the JSON and performing the necessary transformation directly would be easier and more flexible.</p>
<p>For example, we can achieve the same without using the Transformation Service Plugin with a script like this one:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// parse the response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">responseObj</span> <span class="o">=</span> <span class="nx">global</span><span class="p">.</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">responseBody</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// get the records/rows inside the &#34;result&#34;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">records</span> <span class="o">=</span> <span class="nx">responseObj</span><span class="p">[</span><span class="s2">&#34;result&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">altResults</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Loop all records[i]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">records</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">resultObj</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">first_name</span> <span class="o">=</span> <span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">first_name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">last_name</span> <span class="o">=</span> <span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">last_name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">user</span> <span class="o">=</span> <span class="s2">&#34;User &#34;</span> <span class="o">+</span> <span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">first_name</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">last_name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// email
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">var</span> <span class="nx">email</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">email</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;@&#39;</span><span class="p">)</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span> <span class="p">){</span>
</span></span><span class="line"><span class="cl">        <span class="nx">email</span> <span class="o">=</span>  <span class="s2">&#34;***@&#34;</span> <span class="o">+</span> <span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">email</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;@&#39;</span><span class="p">)[</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">email</span> <span class="o">=</span> <span class="nx">email</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// active field
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">var</span> <span class="nx">active</span> <span class="o">=</span> <span class="s2">&#34;ACTIVE&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">active</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">        <span class="nx">active</span> <span class="o">=</span> <span class="s2">&#34;INACTIVE&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">active</span> <span class="o">=</span> <span class="nx">active</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// margin
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">invoicePriceHour</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">u_invoiced_price_per_hour</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">u_invoiced_price_per_hour</span> <span class="o">=</span> <span class="nx">invoicePriceHour</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">costHour</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">records</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">u_cost_per_hour</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">u_cost_per_hour</span> <span class="o">=</span> <span class="nx">costHour</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nx">resultObj</span><span class="p">.</span><span class="nx">margin</span> <span class="o">=</span> <span class="nx">invoicePriceHour</span> <span class="o">-</span> <span class="nx">costHour</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">altResults</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">resultObj</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">resultObj</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> 
</span></span></code></pre></div><p>It is quite straightforward and easy to follow for any ServiceNow developper.</p>
<h2 id="performances">Performances</h2>
<p>Also it seems that using Transformation Service Plugin is a bit slower than the JSON parsing alternative.</p>
<p>To figure out how much slower exactly, I added some code to record the time before and after the &ldquo;transformer&rdquo; script and the &ldquo;parser&rdquo; script and calculate the duratio in milliseconds. Here are the results:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">transfomerStart=1592997620426, transfomerEnd=1592997620556, total=130
</span></span><span class="line"><span class="cl">parserStart=1592997620556, parserEnd=1592997620581, total=25
</span></span></code></pre></div><p>I ran it several time and get always similar results, with the &ldquo;transformer&rdquo; script running about 5 times slower the the &ldquo;parser&rdquo; script.</p>
<h1 id="conclusions">Conclusions</h1>
<p>My guess is that it will still be improved and the issues will resolved, but for the time being, unless there is a very specifc reason, I would avoid using this plugin.</p>
<p>For example, it is a pitty that I could not make the calculation work. I odn&rsquo;t know if I am doing something wrong or if the functionnality is somehow broken, but this would be very usefull.</p>
<p>It is not possible to handle conditional cases by setting values based on the values of other fields.</p>
<p>Also when performing mapping, there is no way to reject the value in case it is not in the mapping definition. similarly, there is no possibility to use a default value in such case.</p>
<p>In my opinion, it is (still?) not as flexible and versatile as using a JSON (or XML) parser directly and adding the necessary code to perform all the concatenations, controls, mapping and calculation directly.</p>
<p>However, I am speaking from my point of view and having in mind the transformations I need to perform regularly. But there should be use cases where this plugin is usefull and where it would be advantageous to use it, but I am currently not aware of them.</p>
<h2 id="references">References</h2>
<blockquote>
<p>⚠ When I last checked I noticed that the current documentation for the API is not 100% accurate. For example <code>.fromJSON()</code> and <code>.fromXML()</code> are not detailed (they are just mentionned in the introduction) and in the examples there is sometime methods that doesn&rsquo;t exist, like a <code>.addMultiply</code>. Also the examples involving calculation using elements of the source are not working well, as we saw above.</p>
</blockquote>
<ol>
<li>ServiceNow documentation, <a href="https://developer.servicenow.com/dev.do#!/reference/api/orlando/server/sn_tfrm-namespace/TransformerScriptedAPI">Transformer API</a>,  accessed 2020 06 22</li>
<li>ServiceNow documentation, <a href="https://developer.servicenow.com/dev.do#!/reference/api/orlando/server/sn_tfrm-namespace/TransformerDefinitionAPI">TransformerDefinition API</a>,  accessed 2020 06 22</li>
<li>ServiceNow documentation, <a href="https://developer.servicenow.com/dev.do#!/reference/api/orlando/server/sn_tfrm-namespace/TransformerRuleListAPI">TransformerRulesList API</a>, accessed 2020 06 22</li>
<li><em>complete script snippet</em> can be accessed <a href="https://gitlab.com/samuelmeylan/www.snow-adventures.com/snippets/1989764">here</a></li>
</ol>]]></content:encoded>
    </item>
    
    <item>
      <title>Overview of GlideQuery</title>
      <link>https://www.snow-adventures.com/posts/overview-of-glidequery/</link>
      <pubDate>Wed, 10 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://www.snow-adventures.com/posts/overview-of-glidequery/</guid>
      <description>Insights about the new GlideQuery functionnality</description>
      <content:encoded><![CDATA[<h1 id="overview-of-glidequery">Overview of GlideQuery</h1>
<p>This overview is mostly a coming from the breakout presentation done by <a href="https://events.servicenow.com/widget/servicenow/knowledge2020/myagenda/session/1581555110988001mNP1?sessionId=1581555110988001mNP1">Peter Bell during knowledge 2020</a>.</p>
<p>Currently this feature is not available in the platform but is part of the ITAM plugin. However it will likely be available in future releases like Paris or Quebec.</p>
<p>In the meantime, it is possible to activate <code>GlideQuery</code>in your personal instance. See below the instructions to do so.</p>
<p>There is also a <a href="../glidequery-cheat-sheet/">Cheat Sheet</a> available for help you playing around with this functionnality.</p>
<h2 id="what-is-glidequery">What is GlideQuery</h2>
<ul>
<li><code>GlideQuery</code> is Server script API
<ul>
<li>it consists of 2 global script includes:
<ul>
<li><code>GlideQuery</code>, to which we can have a look (non protected)</li>
<li><code>GlideQueryEvaluator</code>, which is protected, therefore it is not possible to have a look at it.</li>
</ul>
</li>
</ul>
</li>
<li>It is said that it use <code>GlideRecord</code> under the hood, probably inside the <code>GlideQueryEvaluator</code> script</li>
<li>It also replace <code>GlideAggregate</code> in some cases (in particular for counting records)</li>
<li>it is 100% JavaScript.</li>
</ul>
<p>So it will not replace <code>GlideRecord</code>, but it proposes an additional layer on the top of it, that offers several benefits to the developers. Mainly it should reduce the likelihood of errors and mistakes when manipulating <code>GlideRecord</code> and make it&rsquo;s usage clearer and easier.</p>
<h2 id="three-principles-of-glidequery">Three principles of GlideQuery</h2>
<p>Peter Bell states that <code>GlideQuery</code> has 3 principles, that are:</p>
<ul>
<li>Fail fast: runs into errors as soon as possible, offering a quick feedback loop</li>
<li>Be JavaScript: behave like a normal JavaScript library. The <code>GlideRecord</code> is sometime confusing and behave more like Java.</li>
<li>Be expressive: allows to do more with less code</li>
</ul>
<p>We will se below more in details what that means.</p>
<h3 id="fail-fast">Fail fast</h3>
<p>By &ldquo;Fail fast&rdquo; it means that the query should run into error if anything is potentially wrong and therefore this can be spotted and corrected early. For example:</p>
<ul>
<li>Field name checking</li>
<li>Choice value checking</li>
<li>Type checking</li>
<li>Check if any Business Rule rejects the update/insert</li>
</ul>
<p>Here below are some examples that shows the differences between <code>GlideRecord</code> and <code>GlideQuery</code></p>
<h4 id="field-name-checking">Field Name Checking</h4>
<p><code>GlideQuery</code>checks that the field name used in the query are valid and if not it will raise an error.</p>
<p>For example, running the following code with <code>GlideRecord</code>, it will delete <em>all</em> the records from the Users table, even if the field <code>activated</code> is wrong:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">gr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">addQuery</span><span class="p">(</span><span class="s1">&#39;actived&#39;</span><span class="p">,</span> <span class="s1">&#39;!=&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">getRowCount</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">deleteMultiple</span><span class="p">();</span>
</span></span></code></pre></div><p>If we run the equivalent with <code>GlideQuery</code>, it will fail and give an error instead:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;activated&#39;</span><span class="p">,</span> <span class="s1">&#39;!=&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">del</span><span class="p">();</span>
</span></span></code></pre></div><p>This will return an error:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">*** Script: Unknown field &#39;closed_date&#39; in table &#39;task&#39;. Known fields:
</span></span><span class="line"><span class="cl">[
</span></span><span class="line"><span class="cl">  &#34;parent&#34;,
</span></span><span class="line"><span class="cl">  &#34;made_sla&#34;,
</span></span><span class="line"><span class="cl">  ...
</span></span><span class="line"><span class="cl">]
</span></span></code></pre></div><h4 id="choice-value-checking">Choice value checking</h4>
<p><code>GlideQuery</code>is also checking for the choice value when choice fields are involved in the query.</p>
<p>For example, running the following code with <code>GlideRecord</code>, it will not return anything.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">gr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">addQuery</span><span class="p">(</span><span class="s1">&#39;approval&#39;</span><span class="p">,</span> <span class="s1">&#39;donotexist&#39;</span><span class="p">);</span> <span class="c1">// we use an invalid value for the choice field &#39;approval&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">gr</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">next</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">getDisplayValue</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>If we run the equivalent with <code>GlideQuery</code>, it will fail and give an error instead:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">tasks</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;approval&#39;</span><span class="p">,</span> <span class="s1">&#39;donotexist&#39;</span><span class="p">)</span> <span class="c1">// we use an invalid value for the choice field &#39;approval&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;number&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">gs</span><span class="p">.</span><span class="nx">log</span><span class="p">);</span>
</span></span></code></pre></div><p>This will return an error:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">*** Script: Invalid choice &#39;donotexist&#39; for field &#39;approval&#39; (table &#39;task&#39;). Allowed values:
</span></span><span class="line"><span class="cl">[
</span></span><span class="line"><span class="cl">  &#34;not requested&#34;,
</span></span><span class="line"><span class="cl">  &#34;requested&#34;,
</span></span><span class="line"><span class="cl">  &#34;approved&#34;,
</span></span><span class="line"><span class="cl">  &#34;rejected&#34;,
</span></span><span class="line"><span class="cl">  &#34;cancelled&#34;,
</span></span><span class="line"><span class="cl">  &#34;not_required&#34;,
</span></span><span class="line"><span class="cl">  &#34;duplicate&#34;
</span></span><span class="line"><span class="cl">]: no thrown error
</span></span></code></pre></div><p>Strangely, it seems to work only with choice fields that have String value. For example this code do not raise any error, despite the state 8 doesn&rsquo;t exist</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">tasks</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;state&#39;</span><span class="p">,</span> <span class="mi">8</span> <span class="cm">/*do not exist!*/</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;number&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">gs</span><span class="p">.</span><span class="nx">log</span><span class="p">);</span>
</span></span></code></pre></div><h3 id="type-checking">Type checking</h3>
<p><code>GlideQuery</code>is also checking if there the value is of the correct type. For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">tasks</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;approval&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="c1">// we pass an Integer instead of a String
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;number&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">gs</span><span class="p">.</span><span class="nx">log</span><span class="p">);</span>
</span></span></code></pre></div><p>Will return an error:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">** Script: Unable to match value 3 with field &#39;approval&#39; in table &#39;task&#39;. Expecting type &#39;string&#39;: no thrown error
</span></span><span class="line"><span class="cl">Root cause of JavaScriptException: org.mozilla.javascript.NativeError
</span></span></code></pre></div><h4 id="check-if-any-business-rule-rejects-the-updateinsert">Check if any Business Rule rejects the update/insert</h4>
<p>This is another difference with <code>GlideRecord</code>: when a Business Rule abort the insert or update action, then the script would continue, ignoring this error. With <code>GlideQuery</code>, it would rather stop.</p>
<p>For example, running the following code with <code>GlideRecord</code>, it will continue executing, despite that a business rule aborted the action due to start date being after the end date.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">gr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;change_request&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;c83c5e5347c12200e0ef563dbb9a7190&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">setValue</span><span class="p">(</span><span class="s1">&#39;work_end&#39;</span><span class="p">,</span> <span class="s1">&#39;2016-01-01&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">setValue</span><span class="p">(</span><span class="s1">&#39;work_start&#39;</span><span class="p">,</span> <span class="s1">&#39;2020-01-01&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">update</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;executing this line?&#34;</span><span class="p">);</span> <span class="c1">//yes, it will execute this line despite the error in the Business rule preventing the start data after the end date
</span></span></span></code></pre></div><p>If we run the equivalent with <code>GlideQuery</code>, it will fail and give an error instead:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;change_request&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;sys_id&#39;</span><span class="p">,</span> <span class="s1">&#39;c83c5e5347c12200e0ef563dbb9a7190&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">update</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    	<span class="nx">work_end</span><span class="o">:</span> <span class="k">new</span> <span class="nx">GlideDateTime</span><span class="p">(</span><span class="s1">&#39;2016-01-01&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    	<span class="nx">work_start</span><span class="o">:</span> <span class="k">new</span> <span class="nx">GlideDateTime</span><span class="p">(</span><span class="s1">&#39;2020-01-01&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;executing this line?&#34;</span><span class="p">);</span>
</span></span></code></pre></div><p>This will return an error:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">*** Script: {
</span></span><span class="line"><span class="cl">  &#34;message&#34;: &#34;Failure to update table&#34;,
</span></span><span class="line"><span class="cl">  &#34;table&#34;: &#34;change_request&#34;,
</span></span><span class="line"><span class="cl">  &#34;lastGlideError&#34;: &#34;Operation against file &#39;change_request&#39; was aborted by Business Rule &#39;Actual Start/End Date Validation^c83c5e5347c12200e0ef563dbb9a7190&#39;. Business Rule Stack:Actual Start/End Date Validation&#34;,
</span></span><span class="line"><span class="cl">  &#34;changes&#34;: {
</span></span><span class="line"><span class="cl">    &#34;work_end&#34;: {},
</span></span><span class="line"><span class="cl">    &#34;work_start&#34;: {}
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">}: no thrown error
</span></span></code></pre></div><h3 id="be-javascript">Be JavaScript</h3>
<h4 id="stringly--typed-values">Stringly  typed values</h4>
<p>WIth <code>GlideRecord</code> there is frequently issues with the type of value returned. For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">gr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">addQuery</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="s1">&#39;Abel&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">next</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">first_name</span><span class="p">);</span> <span class="c1">// -&gt; Abel
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">firt_name</span> <span class="o">===</span> <span class="s1">&#39;Abel&#39;</span><span class="p">);</span> <span class="c1">// -&gt; false 🤔
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="k">typeof</span> <span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">first_name</span><span class="p">));</span> <span class="c1">// -&gt; object
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>The reason is that the <code>first_name</code>is a java object. Another example with <code>GlideRecord</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">gr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">gr</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">gr</span><span class="p">.</span><span class="nx">next</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">gr</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// will return &#34;0&#34; or &#34;-1&#34; as string, and it evaluated always as true...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="c1">//doSomething(gr); 
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Last example with GlideAgregate</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">taskGa</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideAgregate</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">taskGa</span><span class="p">.</span><span class="nx">addAggregate</span><span class="p">(</span><span class="s1">&#39;COUNT&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">taskGa</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">taskGa</span><span class="p">.</span><span class="nx">next</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">rowCount</span> <span class="o">=</span> <span class="nx">taskGa</span><span class="p">.</span><span class="nx">getAggregate</span><span class="p">(</span><span class="s1">&#39;COUNT&#39;</span><span class="p">);</span> <span class="c1">// -&gt; return a String (&#34;123&#34;)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// With GlideQuery
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">rowCount</span> <span class="o">=</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">).</span><span class="nx">count</span><span class="p">();</span> <span class="c1">// -&gt; return a number (123)
</span></span></span></code></pre></div><p>With <code>GlideQuery</code> all this example are solved: it return a javascript object, where the <code>key</code> is the field name and the <code>value</code> the actual value of the field:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">gr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">whereNotNull</span><span class="p">(</span><span class="s1">&#39;parent&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">selectOne</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;parent.urgency&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">get</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">gr</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/* returns
</span></span></span><span class="line"><span class="cl"><span class="cm">{
</span></span></span><span class="line"><span class="cl"><span class="cm">  &#34;description&#34;: null,
</span></span></span><span class="line"><span class="cl"><span class="cm">  &#34;active&#34;: false,
</span></span></span><span class="line"><span class="cl"><span class="cm">  &#34;parent&#34;: {
</span></span></span><span class="line"><span class="cl"><span class="cm">    &#34;urgency&#34;: 3
</span></span></span><span class="line"><span class="cl"><span class="cm">  },
</span></span></span><span class="line"><span class="cl"><span class="cm">  &#34;sys_id&#34;: &#34;801a087adba52200a6a2b31be0b8f520&#34;
</span></span></span><span class="line"><span class="cl"><span class="cm">}
</span></span></span><span class="line"><span class="cl"><span class="cm">*/</span>
</span></span></code></pre></div><h4 id="be-expressive">Be expressive</h4>
<p>For reading the data, there is Stream, that apply when reading multiple records and Optional, used for a single record.</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>Stream</th>
          <th>Optional</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Returned by</td>
          <td>select()</td>
          <td>SelectOne(), insert(), update()</td>
      </tr>
      <tr>
          <td>Common methods</td>
          <td>map, flatMap, forEach, reduce, some, any</td>
          <td>get, map, isEmpty, isPresent, ifPresent, orElse</td>
      </tr>
      <tr>
          <td>Comments</td>
          <td>is <a href="https://en.wikipedia.org/wiki/Lazy_evaluation">lazy evaluated</a></td>
          <td></td>
      </tr>
  </tbody>
</table>
<p>Here below are code examples that shows some of the methods in action.</p>
<h4 id="example-with-map-and-foreach">Example with map and forEach</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">whereNotNull</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">user</span><span class="p">)</span> <span class="p">{</span><span class="k">return</span> <span class="nx">user</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">();</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">gs</span><span class="p">.</span><span class="nx">log</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// will return a list of name in upper case
</span></span></span></code></pre></div><h4 id="example-with-some-and-every">Example with some and every</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">hasOnlyShortDescription</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">whereNotNull</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">every</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="c1">// checks that all records match the condition
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">hasLongDescriptions</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">whereNotNull</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">1000</span><span class="p">;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="c1">// checks that at least one record matched the condition
</span></span></span></code></pre></div><h4 id="examples-with-insert-update-delete">Examples with insert, update, delete</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Insert
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">insert</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    	<span class="nx">active</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    	<span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Sam Meylan&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    	<span class="nx">city</span><span class="o">:</span> <span class="s1">&#39;Geneva&#39;</span>
</span></span><span class="line"><span class="cl">	<span class="p">})</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">get</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// delete
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">disableWorkflow</span><span class="p">()</span> <span class="c1">// disable the business rules
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="p">.</span><span class="nx">deleteMultiple</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// update
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;sys_id&#39;</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">update</span><span class="p">({</span><span class="nx">priority</span><span class="o">:</span> <span class="mi">1</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">updateMultiple</span><span class="p">({</span><span class="nx">order</span><span class="o">:</span> <span class="mi">1</span><span class="p">});</span>
</span></span></code></pre></div><h4 id="examples-with-aggregation">Examples with aggregation</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">companyCount</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;core_company&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;city&#39;</span><span class="p">,</span> <span class="s1">&#39;Berlin&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">count</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">maxReopenCount</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="s1">&#39;reopen_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="c1">// will return the max count or 0 if there is no
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">groupBy</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">aggregate</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="s1">&#39;reassignment_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">having</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="s1">&#39;reassignement_count&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">toArray</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* return
</span></span></span><span class="line"><span class="cl"><span class="cm">[
</span></span></span><span class="line"><span class="cl"><span class="cm">  {
</span></span></span><span class="line"><span class="cl"><span class="cm">    &#34;group&#34;: {
</span></span></span><span class="line"><span class="cl"><span class="cm">      &#34;priority&#34;: 1
</span></span></span><span class="line"><span class="cl"><span class="cm">    },
</span></span></span><span class="line"><span class="cl"><span class="cm">    &#34;sum&#34;: {
</span></span></span><span class="line"><span class="cl"><span class="cm">      &#34;reassignment_count&#34;: 11
</span></span></span><span class="line"><span class="cl"><span class="cm">    }
</span></span></span><span class="line"><span class="cl"><span class="cm">  },
</span></span></span><span class="line"><span class="cl"><span class="cm">  {
</span></span></span><span class="line"><span class="cl"><span class="cm">    &#34;group&#34;: {
</span></span></span><span class="line"><span class="cl"><span class="cm">      &#34;priority&#34;: 2
</span></span></span><span class="line"><span class="cl"><span class="cm">    },
</span></span></span><span class="line"><span class="cl"><span class="cm">    &#34;sum&#34;: {
</span></span></span><span class="line"><span class="cl"><span class="cm">      &#34;reassignment_count&#34;: 3
</span></span></span><span class="line"><span class="cl"><span class="cm">    }
</span></span></span><span class="line"><span class="cl"><span class="cm">  },
</span></span></span><span class="line"><span class="cl"><span class="cm">  ...
</span></span></span><span class="line"><span class="cl"><span class="cm">  */</span>
</span></span></code></pre></div><h4 id="flags">Flags</h4>
<p>Flags are additional indicators that can be added to the field name to request thinks like the display (<code>$DISPLAY</code>) value or the currency code (<code>$CURRENCY_CODE</code>).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;company$DISPLAY&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">doSomething</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;core_company&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">selectOne</span><span class="p">(</span><span class="s1">&#39;market_cap&#39;</span><span class="p">,</span> <span class="s1">&#39;market_cap$CURRENCY_CODE&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">get</span><span class="p">()</span>
</span></span></code></pre></div><h4 id="complex-queries">Complex queries</h4>
<p>Complex queries are queries involving OR conditions or nested conditions.</p>
<p>For example with <code>GlideRecord</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">taskGr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">taskGr</span><span class="p">.</span><span class="nx">addQuery</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">addCondition</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">addOrCondition</span><span class="p">(</span><span class="s1">&#39;severity&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span></span></code></pre></div><p>How will this be evaluated? it is ambiguous and it could be :</p>
<ol>
<li>(active = true AND priority = 1) OR severity = 1</li>
<li><strong>active = true AND (priority = 1 OR severity = 1)</strong></li>
</ol>
<p>The correct answer is the second one. With GlideRecord, OR has priority over AND.</p>
<p>With GlideQuery, the ambiguity is reduced and things are clearer:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// active = true AND (priority = 1 OR severity = 1)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">orWhere</span><span class="p">(</span><span class="s1">&#39;severity&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">,</span> <span class="s1">&#39;assgined_to&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">doSomething</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// manager is NULL OR ( title = &#39;Vice President&#39; AND state = &#39;CA&#39;)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">whereNull</span><span class="p">(</span><span class="s1">&#39;manager&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;Vice President&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">orWhere</span><span class="p">(</span><span class="s1">&#39;state&#39;</span><span class="p">,</span> <span class="s1">&#39;CA&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">doSomething</span><span class="p">)</span>
</span></span></code></pre></div><p>The main difference is the use of a GlideQuery inside the GlideQuery. This force the parenthesis explicitly in the query.</p>
<h2 id="performance">performance</h2>
<p>The use of the `GlideQuery&rsquo;  add an overhead of about 4% to 6%, mainly due to the conversions done from java to javascript.</p>
<p>But we need to keep in mind that in many cases we would do this conversions anyway after the query, when using the data retrieved from the database.</p>
<p>Also it force good practices from a performance point of view. For example, when querying for a single record with <code>GlideRecord</code>, we should add <code>.setLimit()</code>but it is often forgotten. <code>GlideQuery</code>uses <code>selectOne()</code> for this purpose.</p>
<p>Also the <code>getRowCount</code>should not be used to count the record, as the underlying query to the database will query all the records. The <code>GlideAggregate</code>with a <code>count</code>shoud be used instead. <code>GlideQuery</code>offers here an easiest way to achieve this with <code>.count()</code>.</p>
<h2 id="immutability-and-reuse">Immutability and reuse</h2>
<p>The <code>GlideQuery</code>is an immutable object. This means that it can be passed to a function and we don&rsquo;t care what the function is doing with it, unlike with <code>GlideRecord</code>.</p>
<p>It allows also to reuse the query and extend it. Here below some examples:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Javascript" data-lang="Javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">highPriorityTasks</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">generateReport</span><span class="p">(</span><span class="nx">highPriorityTasks</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">notifyOwner</span><span class="p">(</span><span class="nx">highPriorityTasks</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">avgReassignmentCount</span> <span class="o">=</span> <span class="nx">highPriorityTasks</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">avg</span><span class="p">(</span><span class="s1">&#39;reassignment_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span></code></pre></div><h2 id="how-to-enable-it-on-your-instance-for-testing">How to enable it on your instance (for testing)</h2>
<p>So now that we went through a lot of explanations, you will probably want to try by yourself. As stated at the beginning, it is (still) not included in a vanilla instance, but it is part of the ITAM plugin.</p>
<p>Luckily, despite being part of the ITAM plugin, it is possible to enable GlideQuery on your instance and play with it.</p>
<p>Do to so, run the following script:</p>
<blockquote>
<p>⚠Try this in your personal instance only. I would not recommend to use this in a productive environment at the moment. It will likely be evolve and will eventually be integrated in Paris or Quebec release.</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">pluginArr</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;com.sn_glidequery&#39;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">pluginMgr</span><span class="o">=</span> <span class="k">new</span> <span class="nx">GlideMultiPluginManagerWorker</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">pluginMgr</span><span class="p">.</span><span class="nx">setPluginIds</span><span class="p">(</span><span class="nx">pluginArr</span> <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">pluginMgr</span><span class="p">.</span><span class="nx">setProgressName</span><span class="p">(</span><span class="s2">&#34;Plugin Installer&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">pluginMgr</span><span class="p">.</span><span class="nx">setBackground</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">pluginMgr</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div><h3 id="checking--the-code">Checking  the code</h3>
<p>Now that is it installed, you can go in the script includes and look for the <code>GlideQuery</code> script include. It is open and you can read all the code. It is quite interesting well documented. It can also gives you some insights about what can be done and how to use it.</p>
<h2 id="cheat-sheet">Cheat Sheet</h2>
<p>There is a <a href="../glidequery-cheat-sheet/">Cheat Sheet</a> available for help you playing around with this functionnality.</p>
<h2 id="references">References</h2>
<ol>
<li>Peter Bell, breakout  <a href="https://events.servicenow.com/widget/servicenow/knowledge2020/myagenda/session/1581555110988001mNP1?sessionId=1581555110988001mNP1">GlideQuery: A modern upgrade to GlideRecord CCB3052</a>, accessed 2020 06 12</li>
<li>Jace Benson, <a href="https://jace.pro/post/2020-04-28-what-is-glidequery/">What is GlideQuery</a>, 2020 04 28</li>
</ol>]]></content:encoded>
    </item>
    
    <item>
      <title>Using remote tables in ServiceNow</title>
      <link>https://www.snow-adventures.com/posts/using-remote-tables-in-servicenow/</link>
      <pubDate>Wed, 10 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://www.snow-adventures.com/posts/using-remote-tables-in-servicenow/</guid>
      <description>Smoke tests with remote tables functionnality</description>
      <content:encoded><![CDATA[<h2 id="what-are-remote-tables">What are remote tables</h2>
<p>Since the New York release, ServiceNow offers a new functionality called <em>remote tables</em>.</p>
<p>Remote tables allows to query and retrieves data from other systems, via REST/SOAP and use them almost seamlessly in service-now.</p>
<p>The remote table can be used like a standard, local,  table:</p>
<ul>
<li>They can be queried by script;</li>
<li>We can see the records in lists or in forms;</li>
<li>Reports can be run on the data;</li>
<li>They can be used as reference from other tables (both local or remote tables);</li>
<li>They support, like standard tables, sorting, aggregating and filtering like internal tables;</li>
</ul>
<p>The obvious case is to retrieve data from a remote system, but there is nothing that prevent us to also use local tables or a mix of remote and local tables and present them as one remote table. We can also see the remote tables like a kind of enhanced database view, that allows for example to :</p>
<ul>
<li>aggregating data from multiple sources, both local or remote;</li>
<li>Making calculations;</li>
<li>Applying logic and complex conditions;</li>
</ul>
<p>There is also an option to cache the data that has been retrieved for a certain time, to reduce the load and improve performances.</p>
<p>As you can see, Remote tables are a nice feature to use external data in ServiceNow and have them always up to date. It can be use in numerous scenario where external data need to be always up to date and when it is OK to have it read-only in ServiceNow.</p>
<p>In this article, we will play around and try different use of the remote tables. It will of course not cover all the use cases but it will give a good overview of what can be achieved.</p>
<h2 id="the-different-use-cases">The different use cases</h2>
<p>For this test case, we will link an external table to ServiceNow using the remote table functionality.</p>
<p>As a first step, we will link the user table from an ServiceNow instance, using REST. We will include a few fields, including one reference field to Company and see how it react.</p>
<p>Then we will see how to retrieve the Company data in the remote table (like the company name) and see how to include also local data and set custom data in the remote table like calculation result.</p>
<p>Next step will be to use our remote table in a reference field on a local table (like on the incident table) and see what happen</p>
<p>Then we will create a new remote table for companies and see how we can make a reference from a remote table to another table</p>
<p>Finally we will see during all the article what should be done to optimize the query of the remote table, as the default behavior of our setup is to query always all the records.</p>
<p>For the sack of simplicity, both the source table and the remote table are on the same instance. But for make it more realistic (like if we are not querying another ServiceNow instance), we will not rely on the sys_id of the remote user table and we will user the UserId as the key. For the company table, we will use the sys_id, in order to not overcomplicate the example.</p>
<h2 id="creation-the-remote-table">Creation the Remote Table</h2>
<p>Let&rsquo;s start by creating our remote rable.</p>
<p>There are three main steps:</p>
<ul>
<li>Define the table in the dictionary, where we set the table name, the columns and all the standard options for a table;</li>
<li>Create a REST message to connect to the source table we want to query;</li>
<li>Create the related Script Definition that query the source with the REST message and present the data in the Remote Table.</li>
</ul>
<blockquote>
<p>⚠Remote table plugin activation</p>
<p>Before using the Remote tables, check that the corresponding plug-in (com.glide.script.vtable) is activated. If this is not the case, activate it.</p>
</blockquote>
<h3 id="define-the-table-in-the-dictionary">Define the table in the dictionary</h3>
<p>To define the table in the dictionary, go in the menu <em>System Definition - Remote Tables - Tables</em> and click <em>New</em>.</p>
<blockquote>
<p>⚠  there is currently no possibility to create Remote Table from the Studio. You need to create them from the menu and only after this they will appear in the Studio.</p>
</blockquote>
<p>Fill in the name and choose whether or not you want to create a module, and check all the usual options for table creation (roles, etc.).</p>
<p>Then you need to add in the Columns list all the fields that you want on your Remote Table.</p>
<p>For now, we will keep it simple with only the First Name, Last Name, Company, Active, Phone and Email.</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608115856545.png"/> <figcaption>
            Remote User definition
        </figcaption>
</figure>

<blockquote>
<p>ℹ The Sys_id field is automatically created. Note that there is not the other usual systems fields like sys_created_on, sys_update_by, etc.</p>
</blockquote>
<h3 id="create-the-rest-message">Create the REST message</h3>
<p>Let&rsquo;s create a REST message to the user table in our own instance, using the following settings:</p>
<ul>
<li>Endpoint : <a href="https://xxx.service-now.com/api/now/table/sys_user">https://xxx.service-now.com/api/now/table/sys_user</a></li>
<li>Authentication: basic - Create a profile and set your own user/password for example</li>
<li>add an HTTP method: Get</li>
<li>add the HTTP Query parameter (in the HTTP method);</li>
</ul>
<h3 id="create-the-related-script-definition">Create the related script definition</h3>
<p>Now the next step is to create a script definition for our new Remote Table. Go to <em>System Definition - Remote Tables - Definitions</em> and click <em>New</em>.</p>
<p>In table select the table you created before and let&rsquo;s start writing the script that will retrieve the remote records and make them available in the Remote Table.</p>
<blockquote>
<p>ℹ You will notice that there is a huge comment at the beginning of the script: it contains the explanation about how to prepare the script and how to use the APIs. I suggest you keep it in your script for reference, as there is not this information elsewhere in the documentation.</p>
</blockquote>
<p>Now the goal of the script is to add rows to the Remote Table, using <code>v_table.addRow</code>. This function expect an object containing all the values. The name of each property in the object should match the name of the field defined in the Remote Table.</p>
<p>So let&rsquo;s write the following script, where we query using the REST message and then build and add the rows to our Remote Table.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="p">(</span><span class="kd">function</span> <span class="nx">executeQuery</span><span class="p">(</span><span class="nx">v_table</span><span class="p">,</span> <span class="nx">v_query</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">try</span> <span class="p">{</span> 
</span></span><span class="line"><span class="cl">		<span class="c1">// get the REST message
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_ws</span><span class="p">.</span><span class="nx">RESTMessageV2</span><span class="p">(</span><span class="s1">&#39;x_12270_remote_tab.my users&#39;</span><span class="p">,</span> <span class="s1">&#39;Get&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// execute it
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">response</span> <span class="o">=</span> <span class="nx">message</span><span class="p">.</span><span class="nx">execute</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// get the response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">responseBody</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getBody</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">httpStatus</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getStatusCode</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// if there is an error, log and return
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">haveError</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">v_query</span><span class="p">.</span><span class="nx">setLastErrorMessage</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">getErrorMessage</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">			<span class="nx">gs</span><span class="p">.</span><span class="nx">addErrorMessage</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">getErrorMessage</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// Parse response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">json</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">global</span><span class="p">.</span><span class="nx">JSON</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">responseObj</span> <span class="o">=</span> <span class="nx">json</span><span class="p">.</span><span class="nx">decode</span><span class="p">(</span><span class="nx">responseBody</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">resultArr</span> <span class="o">=</span> <span class="nx">responseObj</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span> <span class="c1">// all the records are contained in an array &#39;result&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">		<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;</span> <span class="nx">resultArr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">			<span class="c1">//build the row
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kd">var</span> <span class="nx">row</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="c1">// map fields from the result
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="nx">row</span><span class="p">.</span><span class="nx">first_name</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">first_name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nx">row</span><span class="p">.</span><span class="nx">last_name</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">last_name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nx">row</span><span class="p">.</span><span class="nx">active</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">active</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nx">row</span><span class="p">.</span><span class="nx">email</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">email</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nx">row</span><span class="p">.</span><span class="nx">phone</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">phone</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nx">row</span><span class="p">.</span><span class="nx">company</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">company</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="c1">// add the row to the remote table
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="nx">v_table</span><span class="p">.</span><span class="nx">addRow</span><span class="p">(</span><span class="nx">row</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">ex</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">v_query</span><span class="p">.</span><span class="nx">setLastErrorMessage</span><span class="p">(</span><span class="nx">ex</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="nx">gs</span><span class="p">.</span><span class="nx">addErrorMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">ex</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">})(</span><span class="nx">v_table</span><span class="p">,</span> <span class="nx">v_query</span><span class="p">);</span>
</span></span></code></pre></div><p>Now we can test it with the following script (to run in <em>Background script</em>):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">grX_12270RTSRU</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideRecord</span><span class="p">(</span><span class="s1">&#39;x_12270_remote_tab_st_remote_user&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span><span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">next</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s1">&#39;active: &#39;</span> <span class="o">+</span> <span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s1">&#39;company: &#39;</span> <span class="o">+</span> <span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;company&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s1">&#39;email: &#39;</span> <span class="o">+</span> <span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;email&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s1">&#39;first_name: &#39;</span> <span class="o">+</span> <span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s1">&#39;last_name: &#39;</span> <span class="o">+</span> <span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;last_name&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nx">gs</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s1">&#39;phone: &#39;</span> <span class="o">+</span> <span class="nx">grX_12270RTSRU</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;phone&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Also if we open the list of the table, you should see records in it:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image20200608132547250.png"/> <figcaption>
            List of Remote Users
        </figcaption>
</figure>

<p>So far so good: we can see the data from the &lsquo;remote&rsquo; table and use it.</p>
<p>However, if we look carefully, we can see that for the company we only have the sys_id. This is because we do not have the display value in the payload. To get a more user friendly information, like the name of the company, we need to query it and use it in the script definition.</p>
<h4 id="getting-the-company-name-instead-of-the-sys_id">Getting the company name instead of the sys_id</h4>
<p>One easy solution that comes to mind to solve this is to query the remote system with another HTTP method in the same REST message as before and get the company name. Let&rsquo;s see how to do this.</p>
<p>First, let&rsquo;s create a new HTTP method (in the existing REST message) for the company table, in a similar way that the one for querying the users, but with this endpoint: <code>/api/now/table/core_company/${id}</code> (and set a name like <em>GetCompany</em> and use it the the script below).</p>
<p>Then let&rsquo;s create a function <code>getRemoteCompanyName</code> to retrieve the remote company and get the name.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getRemoteCompanyName</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// get the REST message
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_ws</span><span class="p">.</span><span class="nx">RESTMessageV2</span><span class="p">(</span><span class="s1">&#39;x_12270_remote_tab.my users&#39;</span><span class="p">,</span> <span class="s1">&#39;GetCompany&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// set the id of the company we want to retrive
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">message</span><span class="p">.</span><span class="nx">setStringParameter</span><span class="p">(</span><span class="s2">&#34;id&#34;</span><span class="p">,</span> <span class="nx">id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// execute it
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kd">var</span> <span class="nx">response</span> <span class="o">=</span> <span class="nx">message</span><span class="p">.</span><span class="nx">execute</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// get the response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kd">var</span> <span class="nx">responseBody</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getBody</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">httpStatus</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getStatusCode</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// if there is not error, continue
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">response</span><span class="p">.</span><span class="nx">haveError</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// Parse response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="kd">var</span> <span class="nx">responseObj</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">global</span><span class="p">.</span><span class="nx">JSON</span><span class="p">().</span><span class="nx">decode</span><span class="p">(</span><span class="nx">responseBody</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">resultObj</span> <span class="o">=</span> <span class="nx">responseObj</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="c1">// check if the reuslt if ok and return the name
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="k">if</span> <span class="p">(</span><span class="nx">resultObj</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nx">resultObj</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// default empty string
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">return</span> <span class="s2">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">        <span class="nx">gs</span><span class="p">.</span><span class="nx">addErrorMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">ex</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="s2">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>And replace the mapping line with this one:</p>
<pre tabindex="0"><code class="language-javasc" data-lang="javasc">row.company = getRemoteCompanyName(resultArr[i].company.value);
</code></pre><p>If we try it, we now we get the company name, but it pretty slow. The reason is that our script need to query the remote system for each user.</p>
<p>We will see later in this post of the solve this issue.  If performances are too bad, for now just comment the mapping on the company.</p>
<h2 id="adding-calculation-and-local-data-to-the-remote-table">Adding calculation and local data to the remote table</h2>
<p>Now let&rsquo;s see how we can add calculated data to the rows in the remote table and how we can use local data as well.</p>
<p>The calculated data would be simply to add a prefix to the phone number coming from the remote instance.</p>
<p>And local data would be looking incidents where the caller email matches the remote user email and give a count of how many incidents are found.</p>
<p>Both addition to the remote table are quite straightforward: we just need to add the required data in the row.</p>
<h4 id="add-prefix-to-the-phone-number">Add prefix to the phone number</h4>
<p>Simply amend the script to add the prefix to the phone number, like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// add prefix to phone
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">phone</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">phone</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">phone</span> <span class="o">!=</span> <span class="s2">&#34;&#34;</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="nx">phone</span> <span class="o">=</span> <span class="s2">&#34;+123 - &#34;</span> <span class="o">+</span> <span class="nx">phone</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nx">row</span><span class="p">.</span><span class="nx">phone</span> <span class="o">=</span> <span class="nx">phone</span><span class="p">;</span>
</span></span></code></pre></div><p>Now the users that have a phone number will have the prefix added in front</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200609121927495.png"/> <figcaption>
            phone numbers are now prefixed
        </figcaption>
</figure>

<h4 id="add-an-incident-counter">Add an incident counter</h4>
<p>This requirement is a bit more complicated. First of all let&rsquo;s create a new field *incident count&quot; on the Remote User table.</p>
<p>To do this, go in the menu <em>System Definition - Remote Tables - Tables</em>, select the Remote User table and add a new field.</p>
<p>Then in the script definition, let&rsquo;s create a function <code>getIncidentCount</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getIncidentCount</span><span class="p">(</span><span class="nx">email</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="k">try</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// get the incident count where caller email match the given email
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kd">var</span> <span class="nx">incidentGr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideAggregate</span><span class="p">(</span><span class="s2">&#34;incident&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">incidentGr</span><span class="p">.</span><span class="nx">addQuery</span><span class="p">(</span><span class="s2">&#34;caller_id.email&#34;</span><span class="p">,</span> <span class="nx">email</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">incidentGr</span><span class="p">.</span><span class="nx">addAggregate</span><span class="p">(</span><span class="s1">&#39;COUNT&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">incidentGr</span><span class="p">.</span><span class="nx">query</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">incidentGr</span><span class="p">.</span><span class="nx">next</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="nx">incidentGr</span><span class="p">.</span><span class="nx">getAggregate</span><span class="p">(</span><span class="s2">&#34;COUNT&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">        <span class="nx">gs</span><span class="p">.</span><span class="nx">addErrorMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">ex</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>And add the result of the function into the new field on the row:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// add incident count 
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">row</span><span class="p">.</span><span class="nx">incident_count</span> <span class="o">=</span> <span class="nx">getIncidentCount</span><span class="p">(</span><span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">email</span><span class="p">);</span>
</span></span></code></pre></div><p>Now the remote user have the incident counter filled:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200609124029773.png"/> <figcaption>
            Incident counter is filled
        </figcaption>
</figure>

<h2 id="referencing-a-remote-table-from-a-local-table">Referencing a remote table from a local table</h2>
<p>Now that we have the Remote User table defined and working, let&rsquo;s use it in other tables. For example, let&rsquo;s add a new field on the incident table, referencing the Remote User table.</p>
<p>First, let&rsquo;s create a new reference field on the incident table, with reference to the Remote User table.</p>
<p>Then let&rsquo;s try to use it: open the pop-up related list and choose a random Remote User. Before doing so, you will need to edit the reference list layout to add some meaningful fields, like First Name, Last Name and Email.</p>
<p>What happen after selecting the record?  The field Remote User is still empty&hellip;</p>
<p>Why is this? The reason is simple: there is no sys_id defined on our remote table. This means that the reference field don&rsquo;t know how to related to the correct row in the remote table, as sys_id is empty for all the rows of the remote table.</p>
<p>To solve this, we need to populate the sys_id of our rows. This need to be done, as you probably guess,  in the definition script.</p>
<p>We could take the remote system sys_id, but let&rsquo;s pretend we are not retrieving the records from another service-now instance and that we do not have a sys_id coming in. Let&rsquo;s use instead the user ID (<em>user_name</em>), with a prefix &lsquo;remote_&rsquo; added.</p>
<p>Let add this line to our script:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">row</span><span class="p">.</span><span class="nx">sys_id</span> <span class="o">=</span> <span class="s1">&#39;remote_&#39;</span> <span class="o">+</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">user_name</span><span class="p">;</span>
</span></span></code></pre></div><p>If we now go back in the incident and try again to select a Remote User, the value is set in the field and if we save the incident, it remains. We can even preview the record like with a local table (but read-only).</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608142639529.png"/> <figcaption>
            Result after fixing the sys_id
        </figcaption>
</figure>

<p>Technically, it stores what we have set as a sys_id into the reference field:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608144816731.png"/> <figcaption>
            XML view of the field
        </figcaption>
</figure>

<h3 id="change-the-display-value-of-the-remote-table">Change the display value of the remote table</h3>
<p>It would be nicer if we can have something else that the sys_id set as a display value. Is this possible? Yes, of course: just go in the table definition and set the field you want to have as a display value.</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608142842844.png"/> <figcaption>
            Set a display value...
        </figcaption>
</figure>

<p>Back in the incident, we now have the First Name as the display value:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608142939053.png"/> <figcaption>
            ... and enjoy a user friendly value
        </figcaption>
</figure>

<h2 id="query-optimization">Query optimization</h2>
<p>Each time we go in the Remote Table, or we open a specific record, or use it like in the incident, the Remote Table queries the remote system and retrieve all the existing records. This is not optimal and could lead to poor response time.</p>
<p>We could of course enable the caching, but first let&rsquo;s try to optimize the queries.</p>
<p>First let&rsquo;s make a check to know how many records are coming in each time we query the Remote Table:. Add the following the the Remote Table definition script:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">gs</span><span class="p">.</span><span class="nx">addInfoMessage</span><span class="p">(</span><span class="s2">&#34;querying remote users return &#34;</span><span class="o">+</span>  <span class="nx">resultArr</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span><span class="sb">`
</span></span></span></code></pre></div><p>If we now refresh the incident, we see that we query a lot of users, even if we want to display only one record.</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608143854825.png"/> <figcaption>
            it queries always all the records...
        </figcaption>
</figure>

<h3 id="getting-a-single-record">Getting a single record</h3>
<p>To optimye the query, we need somehow to get only the record that is interesting us.</p>
<p>The query helper method <code>v_query.isGet()</code> indicate if the query is a <em>get</em> and that only one record is expected.</p>
<p>We can then query the remote system with a different API call, using this endpoint <code>/api/now/table/sys_user/${id}</code>. The id will be provided by <code>v_query.getSysId()</code>.</p>
<p>That would work like a charm if we didn&rsquo;t decided to use a custom sys_id  (&ldquo;remote_&rdquo; + user_name).</p>
<p>To overcome this, we need instead to use the same endpoint and build a query using the <em>user_name</em>.  Luckily, <code>v_query.getSysId()</code> returns the sys_id stored in the reference field (or coming from a <em>get</em> from <em>GlideRecord</em>), so we can use it in our query.</p>
<p>Let&rsquo;s add the following code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// handle the get case
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span> <span class="p">(</span><span class="nx">v_query</span><span class="p">.</span><span class="nx">isGet</span><span class="p">()){</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// get the sys_id
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">var</span> <span class="nx">sys_id</span> <span class="o">=</span> <span class="nx">v_query</span><span class="p">.</span><span class="nx">getSysId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// remove the remote_ from sys_id
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">sys_id</span> <span class="o">=</span> <span class="nx">sys_id</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="s2">&#34;remote_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">);</span> 
</span></span><span class="line"><span class="cl">    <span class="c1">// build the query
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">message</span><span class="p">.</span><span class="nx">setQueryParameter</span><span class="p">(</span><span class="s2">&#34;sysparm_query&#34;</span><span class="p">,</span> <span class="s2">&#34;user_name=&#34;</span> <span class="o">+</span> <span class="nx">sys_id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>and try to refresh the incident:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608150036336.png"/> <figcaption>
            and now it queries only the requested record
        </figcaption>
</figure>

<p>Our query is now retrieving only the record that is needed.</p>
<h3 id="getting-onl-y-the-records-matching-a-filter">Getting onl y the records matching a filter</h3>
<p>There are multiple cases where we filter the records, for example in a list, in a reference qualifier, etc.</p>
<p>Without anything in place, the remote table don&rsquo;t care about the filer and always triggers a full query to the remote table.</p>
<p>But we can restrict the query to the remote system according the filter set in the query to the remote table.</p>
<h4 id="restrict-the-query-to-the-remote-system">Restrict the query to the remote system</h4>
<p>If we go to the Remote User table and filter, we can see that anyway the Remote Table query all the records from the remote system</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608150502046.png"/> <figcaption>
            when filtering, it queries anyway all the records...
        </figcaption>
</figure>

<p>To avoid this, we need to add a filter on the outgoing REST message.</p>
<p>We can know about the query with the helper function <code>v_query.getEncodedQuery()</code>.</p>
<p>We can also get rid of the part with the <code>isGet</code>that we put in place before, because the encoded query contains in this case <code>'sys_id=xxx'</code>.</p>
<blockquote>
<p>⚠ Of course, depending the backend system, it will probably not be possible to simply use the encoded query. An ad-hoc query would need to be built. There are two functions that can help achieving this, if needed: <code>v_query.getCondition()</code> and <code>v_query.getParameter()</code>.</p>
</blockquote>
<p>For the sys_id, here we need something to put a special handling in place to basically to parse the encoded query, replace <code>sys_id</code>with the name of the field we want (<em>user_name</em>) and remove the prefix <em>remote_</em>.  For more clarity this sys_id handling it is placed in a separate function <code>adaptSysIdQuery()</code>.</p>
<p>So we can modify the script as follow:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// get the encoded query
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">query</span> <span class="o">=</span> <span class="nx">v_query</span><span class="p">.</span><span class="nx">getEncodedQuery</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// set the query, if not empty
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span> <span class="p">(</span><span class="nx">query</span> <span class="o">!=</span> <span class="s2">&#34;&#34;</span> <span class="p">){</span>
</span></span><span class="line"><span class="cl">    <span class="nx">message</span><span class="p">.</span><span class="nx">setQueryParameter</span><span class="p">(</span><span class="s2">&#34;sysparm_query&#34;</span><span class="p">,</span> <span class="nx">adaptSysIdQuery</span> <span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="s2">&#34;user_name&#34;</span><span class="p">,</span> <span class="s2">&#34;remote_&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1">// Function to adapt the sysid for the REST query - replace sys_id with the field name and remove the prefix
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">adaptSysIdQuery</span> <span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">idField</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// if there is no sys_id in the query, return
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="k">if</span> <span class="p">(</span><span class="nx">query</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;sys_id&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="nx">query</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// split each condition
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">queryArr</span> <span class="o">=</span> <span class="nx">query</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;^&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">queryArr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">			<span class="kd">var</span> <span class="nx">elementStr</span> <span class="o">=</span> <span class="nx">queryArr</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="c1">// split each term of the condition
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kd">var</span> <span class="nx">elementArr</span> <span class="o">=</span> <span class="nx">elementStr</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">&#34;=&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="nx">elementArr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&#34;sys_id&#34;</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">				<span class="c1">// replace sys_id by the field name
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>				<span class="nx">elementArr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nx">idField</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="c1">// remove the prefix
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>				<span class="nx">elementArr</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nx">elementArr</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="nx">prefix</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="c1">// reassemble elementArr and set back in queryArr
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>				<span class="nx">queryArr</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">elementArr</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&#34;=&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="c1">// reassemble query and return
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="nx">query</span> <span class="o">=</span> <span class="nx">queryArr</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;^&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">query</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span></code></pre></div><p>Now back on the list, if we refresh we can see that we are querying only the record we need from the list.</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608154308360.png"/> <figcaption>
            and now it queries the records according the filter
        </figcaption>
</figure>

<h2 id="references-between-remote-tables">References between remote tables</h2>
<p>Remember above? With the company field on the Remote User table, we added a function that retrieve the company information from the remote instance and set it in the row.</p>
<p>What about, instead, creating a new remote table for the company and make the reference work between the existing Remote User table?</p>
<h3 id="create-the-remote-company-table">Create the Remote Company table</h3>
<p>To do this, create a Remote Company remote table, in a similar way that for the incident</p>
<p>Add the fields you need on that table. At the moment we really only need the field <em>name</em>. As you are in the dictionnary, set this field <em>name</em> as the display value.</p>
<h3 id="create-a-http-method">Create a HTTP method</h3>
<p>Create a new HTTP method (in the existing REST message) for the company table, in a similar way that the previous for querying the company, but with this endpoint: <code>/api/now/table/core_company</code> (and set a name like <em>GetCompanies</em> and use it the the script below). The difference with the previous endpoint is that now we want to be able to query all the companies, not just only a specific company, hence the use of a different endpoint.</p>
<h3 id="create-the-script-definition">Create the script definition</h3>
<p>Then create the related script definition for the Remote Company table and use the script below. Note that, not like with incident, we are now using the remote record sys_id as a sys_id.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="p">(</span><span class="kd">function</span> <span class="nx">executeQuery</span><span class="p">(</span><span class="nx">v_table</span><span class="p">,</span> <span class="nx">v_query</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">try</span> <span class="p">{</span> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// get the REST message
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sn_ws</span><span class="p">.</span><span class="nx">RESTMessageV2</span><span class="p">(</span><span class="s1">&#39;x_12270_remote_tab.my users&#39;</span><span class="p">,</span> <span class="s1">&#39;GetCompanies&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// get the encoded query
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">query</span> <span class="o">=</span> <span class="nx">v_query</span><span class="p">.</span><span class="nx">getEncodedQuery</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// set the query if not empty
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="k">if</span> <span class="p">(</span><span class="nx">query</span> <span class="o">!=</span> <span class="s2">&#34;&#34;</span> <span class="p">){</span>
</span></span><span class="line"><span class="cl">			<span class="nx">message</span><span class="p">.</span><span class="nx">setQueryParameter</span><span class="p">(</span><span class="s2">&#34;sysparm_query&#34;</span><span class="p">,</span>  <span class="nx">query</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// execute it
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">response</span> <span class="o">=</span> <span class="nx">message</span><span class="p">.</span><span class="nx">execute</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// get the response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">responseBody</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getBody</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">httpStatus</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">getStatusCode</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// if there is an error, log and return
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">haveError</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">v_query</span><span class="p">.</span><span class="nx">setLastErrorMessage</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">getErrorMessage</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">			<span class="nx">gs</span><span class="p">.</span><span class="nx">addErrorMessage</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">getErrorMessage</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="c1">// Parse response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>		<span class="kd">var</span> <span class="nx">json</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">global</span><span class="p">.</span><span class="nx">JSON</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">responseObj</span> <span class="o">=</span> <span class="nx">json</span><span class="p">.</span><span class="nx">decode</span><span class="p">(</span><span class="nx">responseBody</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">resultArr</span> <span class="o">=</span> <span class="nx">responseObj</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span> <span class="c1">// all the records are contained in an array &#39;result&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        
</span></span><span class="line"><span class="cl">		<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;</span> <span class="nx">resultArr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">			<span class="c1">//build the row
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kd">var</span> <span class="nx">row</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="c1">// map fields from the result
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="nx">row</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="c1">// build sys_id
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="nx">row</span><span class="p">.</span><span class="nx">sys_id</span> <span class="o">=</span> <span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">sys_id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="c1">// add the row to the remote table
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="nx">v_table</span><span class="p">.</span><span class="nx">addRow</span><span class="p">(</span><span class="nx">row</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">ex</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">v_query</span><span class="p">.</span><span class="nx">setLastErrorMessage</span><span class="p">(</span><span class="nx">ex</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="nx">gs</span><span class="p">.</span><span class="nx">addErrorMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">ex</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">})(</span><span class="nx">v_table</span><span class="p">,</span> <span class="nx">v_query</span><span class="p">);</span>
</span></span></code></pre></div><p>Now we can try the Remote Company table and check that we get all the records.</p>
<h3 id="adapt-the--remote-user-table">Adapt the  Remote User table</h3>
<p>Let&rsquo;s do now the required adaptation on the Remote User table.</p>
<p>First, go in the dictionary and change the type of the field <em>company</em> to Reference and make it reference to the new Remote Company table.</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608164320222.png"/> <figcaption>
            changing the company to reference
        </figcaption>
</figure>

<p>Then adapt the script definition of the Remote User table to set the value of the field <em>company</em> to the sys_id of the company coming in the payload:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">row</span><span class="p">.</span><span class="nx">company</span> <span class="o">=</span><span class="nx">resultArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">company</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
</span></span></code></pre></div><p>Now let&rsquo;s try to open a Remote User and see if it works:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608164111357.png"/> <figcaption>
            It works from Remote User
        </figcaption>
</figure>

<p>It looks fine. Also from the list:</p>
<figure>
    <img loading="lazy" src="/img/remotetable/image-20200608164130814.png"/> <figcaption>
            ... from the list
        </figcaption>
</figure>

<h2 id="conclusion">Conclusion</h2>
<p>We cover quite some use cases in the examples above. The main idea was to discover this remote tables functionality and to play a bit with them.</p>
<p>The key take away is that remote table are a powerful feature to add in out toolbox. It can be used to help in numerous use case, either using remote data or calculating data on local tables.</p>
<p>Please leave you comments or questions below.</p>
<h2 id="references">References</h2>
<ol>
<li>ServiceNow documentation, <a href="https://docs.servicenow.com/bundle/orlando-servicenow-platform/page/administer/remote-tables/concept/remote-tables.html">Retrieving external data using remote tables and scripts</a>, accessed 2020 06 09</li>
<li>Chuck Tomasi, <a href="https://www.youtube.com/watch?v=gw1Lzuy4bZk">NOWCommunity Live Stream - Topical Deep Dive - Remote tables</a>, broadcasted 2020 05 04</li>
</ol>]]></content:encoded>
    </item>
    
    <item>
      <title>GlideQuery Cheat Sheet</title>
      <link>https://www.snow-adventures.com/posts/glidequery-cheat-sheet/</link>
      <pubDate>Tue, 09 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://www.snow-adventures.com/posts/glidequery-cheat-sheet/</guid>
      <description>an attempt to document GlideQuery functions and methods</description>
      <content:encoded><![CDATA[<p>This is a draft Cheat Sheet for the <code>GlideQuery</code>. Please see this <a href="../overview-of-glidequery/">post</a> for a detailled introduction.</p>
<p>This cheat sheet was build with elements gathered from presentations and blog posts and also from reading the script include. It may not be accurate, might evolve and all comments and corrections are welcome !</p>
<h2 id="invoking-glidequery">invoking <code>GlideQuery</code></h2>
<p>In a similar way that <code>GlideRecord</code>, the table name is passed as a parameter:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">myTable</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;table_name&#39;</span><span class="p">);</span>
</span></span></code></pre></div><h2 id="cheat-sheet">Cheat sheet</h2>
<h3 id="selections-insert-update">Selections, insert, update</h3>
<h4 id="get">get()</h4>
<p>Returns a single record by querying primary key <code>key</code>.</p>
<h5 id="parameters">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>key</td>
          <td>(sys_id)</td>
      </tr>
      <tr>
          <td>Array</td>
          <td>selectedFields</td>
          <td>Additional fields to return in result</td>
      </tr>
  </tbody>
</table>
<h5 id="example">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">     <span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;5137153cc611227c000bbd1bd8cd2005&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="s1">&#39;last_name&#39;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">     <span class="p">.</span><span class="nx">orElse</span><span class="p">({</span> <span class="nx">first_name</span><span class="o">:</span> <span class="s1">&#39;Default&#39;</span><span class="p">,</span> <span class="nx">last_name</span><span class="o">:</span> <span class="s1">&#39;User&#39;</span> <span class="p">});</span>
</span></span></code></pre></div><hr>
<h4 id="getby">getBy()</h4>
<p>Returns a single record, using <code>keyValues</code> as a set of key-values to query by.
getBy assumes the &lsquo;=&rsquo; operator for each key-value.</p>
<h5 id="parameters-1">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Object</td>
          <td>keyValues</td>
          <td>Object where the keys are the name of the fields, and the values are the values.</td>
      </tr>
      <tr>
          <td>Array</td>
          <td>selectedFields</td>
          <td>Additional fields to return in result</td>
      </tr>
  </tbody>
</table>
<h5 id="example-1">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">getBy</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">first_name</span><span class="o">:</span> <span class="s1">&#39;Fred&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">last_name</span><span class="o">:</span> <span class="s1">&#39;Luddy&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span> <span class="p">[</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="s1">&#39;last_name&#39;</span><span class="p">,</span> <span class="s1">&#39;city&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">])</span> <span class="c1">// select first_name, last_name, city, active
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">.</span><span class="nx">orElse</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">         <span class="nx">first_name</span><span class="o">:</span> <span class="s1">&#39;Nobody&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">last_name</span><span class="o">:</span> <span class="s1">&#39;Found&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">city</span><span class="o">:</span> <span class="s1">&#39;Nowhere&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">active</span><span class="o">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span></code></pre></div><hr>
<h4 id="insert">insert()</h4>
<p>Inserts a single record</p>
<h5 id="parameters-2">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Object</td>
          <td>keyValues</td>
          <td>Object containing key-values to insert into table</td>
      </tr>
      <tr>
          <td>Array</td>
          <td>selectedFields</td>
          <td>Fields to return in result Optional</td>
      </tr>
  </tbody>
</table>
<h5 id="example-2">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">insert</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">         <span class="nx">active</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">         <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Sam Meylan&#39;</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">        <span class="nx">city</span><span class="o">:</span> <span class="s1">&#39;Geneva&#39;</span> 
</span></span><span class="line"><span class="cl">    <span class="p">})</span> 
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">get</span><span class="p">();</span>
</span></span></code></pre></div><hr>
<h4 id="insertorupdate">insertOrUpdate()</h4>
<p>Updates an existing record (just like update), however instead of requiring
where calls, it uses the primary key(s) in the recordValues object passed
in. If the primary key(s) isn&rsquo;t there, insertOrUpdate will insert a new
record instead. Returns an Optional of the newly created/updated record.
Often useful when you want to want to ensure a record exists and has the
correct values, as you don&rsquo;t need to check for the record&rsquo;s existence beforehand.</p>
<h5 id="parameters-3">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Object</td>
          <td>changes</td>
          <td>Object containing key-values to update/insert into table</td>
      </tr>
      <tr>
          <td>Array</td>
          <td>selectedFields</td>
          <td>Fields to return in result Optional</td>
      </tr>
  </tbody>
</table>
<h5 id="example-3">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// insert a new record
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">insertOrUpdate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">first_name</span><span class="o">:</span> <span class="s1">&#39;George&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">last_name</span><span class="o">:</span> <span class="s1">&#39;Griffey&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// update existing record
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">insertOrUpdate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">sys_id</span><span class="o">:</span> <span class="s1">&#39;2d0efd6c73662300bb513198caf6a72e&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">first_name</span><span class="o">:</span> <span class="s1">&#39;George&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">last_name</span><span class="o">:</span> <span class="s1">&#39;Griffey&#39;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="update">update()</h4>
<p>Updates an existing record. Requires a where call, specifying all existing primary keys (usually sys_id). Returns an Optional of the newly-updated record.</p>
<h5 id="parameters-4">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Object</td>
          <td>changes</td>
          <td>Object containing key-values to update/insert into table</td>
      </tr>
      <tr>
          <td>Array</td>
          <td>selectedFields</td>
          <td>Fields to return in result Optional</td>
      </tr>
  </tbody>
</table>
<h5 id="example-4">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;sys_id&#39;</span><span class="p">,</span> <span class="nx">userId</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">update</span><span class="p">({</span> <span class="nx">city</span><span class="o">:</span> <span class="s1">&#39;Los Angeles&#39;</span> <span class="p">});</span>
</span></span></code></pre></div><hr>
<h4 id="updatemultiple">updateMultiple()</h4>
<p>Updates all records in the table (specified by preceding where clause with the values contained in the changes object. Returns # of records updated.</p>
<h5 id="parameters-5">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Object</td>
          <td>changes</td>
          <td>Object containing key-values to update/insert into table</td>
      </tr>
  </tbody>
</table>
<h5 id="example-5">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;last_name&#39;</span><span class="p">,</span> <span class="s1">&#39;Griffey&#39;</span><span class="p">)</span><span class="o">&lt;</span><span class="nx">r</span><span class="o">&gt;</span>    <span class="p">.</span><span class="nx">updateMultiple</span><span class="p">({</span> <span class="nx">active</span><span class="o">:</span> <span class="kc">true</span> <span class="p">});</span>
</span></span></code></pre></div><hr>
<h4 id="select">select()</h4>
<p>Specifies which fields to return and returns a Stream containing the results of the query. Note that records aren&rsquo;t actually read from the database until a terminal Stream method is called (such as reduce() or toArray()). The Stream is intended for reading multiple records in a similar fashion to Java&rsquo;s Stream class.</p>
<h5 id="parameters-6">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>&hellip;String</td>
          <td>fields</td>
          <td>Fields to select</td>
      </tr>
  </tbody>
</table>
<h5 id="example-6">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">stream</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="s1">&#39;last_name&#39;</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="selectone">selectOne()</h4>
<p>Similar to <code>select()</code>, however only returns an Optional which may contain a single record. This is more efficient than <code>select()</code> if you only need one record, or want to test if a record exists.</p>
<h5 id="parameters-7">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>&hellip;String</td>
          <td>fields</td>
          <td>Fields to select</td>
      </tr>
  </tbody>
</table>
<h5 id="example-7">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;zip&#39;</span><span class="p">,</span> <span class="s1">&#39;12345&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">whereNotNull</span><span class="p">(</span><span class="s1">&#39;last_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">selectOne</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="s1">&#39;last_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">get</span><span class="p">();</span>
</span></span></code></pre></div><hr>
<h4 id="del">Del()</h4>
<p>Deletes all records in the table specified by preceding where clauses</p>
<h5 id="example-8">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;last_name&#39;</span><span class="p">,</span> <span class="s1">&#39;Jeter&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">del</span><span class="p">();</span>
</span></span></code></pre></div><h3 id="conditions">Conditions</h3>
<h4 id="where">where()</h4>
<p>Returns a new GlideQuery containing where clause</p>
<h5 id="parameters-8">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Field related to the where clause</td>
      </tr>
  </tbody>
</table>
<h5 id="example-9">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;last_login&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;2016-04-15&#39;</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="wherenotnull">whereNotNull()</h4>
<p>Returns a new GlideQuery containing NOT NULL clause</p>
<h5 id="parameters-9">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Field related to the clause</td>
      </tr>
  </tbody>
</table>
<h5 id="example-10">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">whereNotNull</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">)</span>
</span></span></code></pre></div><hr>
<h4 id="wherenull">whereNull()</h4>
<p>Returns a new GlideQuery containing WHERE NULL clause</p>
<h5 id="parameters-10">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Field related to the clause</td>
      </tr>
  </tbody>
</table>
<h5 id="example-11">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">whereNull</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">)</span>
</span></span></code></pre></div><h3 id="aggregations">Aggregations</h3>
<h4 id="avg">avg()</h4>
<p>Returns the aggregate average of a given numeric field</p>
<h5 id="parameters-11">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Numeric field</td>
      </tr>
  </tbody>
</table>
<h5 id="example-12">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">faults</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;cmdb_ci&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">avg</span><span class="p">(</span><span class="s1">&#39;fault_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="max">max()</h4>
<p>Returns the aggregate minimum of a given field</p>
<h5 id="parameters-12">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>field</td>
      </tr>
  </tbody>
</table>
<h5 id="example-13">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">faults</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;cmdb_ci&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="min">min()</h4>
<p>Returns the aggregate maximum of a given field</p>
<h5 id="parameters-13">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>field</td>
      </tr>
  </tbody>
</table>
<h5 id="example-14">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">faults</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;cmdb_ci&#39;</span><span class="p">)</span>    
</span></span><span class="line"><span class="cl">	<span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="s1">&#39;sys_mod_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="sum">sum()</h4>
<p>Returns the aggregate sum of a given numeric field</p>
<h5 id="parameters-14">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Numeric field</td>
      </tr>
  </tbody>
</table>
<h5 id="example-15">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">totalFaults</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;cmdb_ci&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">sum</span><span class="p">(</span><span class="s1">&#39;fault_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orElse</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="count">count()</h4>
<p>Returns the row count of records matching the query</p>
<h5 id="example-16">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">userCount</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">count</span><span class="p">();</span>
</span></span></code></pre></div><hr>
<h4 id="groupby">groupBy()</h4>
<p>Groups query results. Used with <code>aggregate()</code></p>
<h5 id="example-17">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">aggregate</span><span class="p">(</span><span class="s1">&#39;count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">groupBy</span><span class="p">(</span><span class="s1">&#39;contact_type&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">select</span><span class="p">();</span>
</span></span></code></pre></div><hr>
<h4 id="aggregate">aggregate()</h4>
<p>Aggregates a field using an aggregate function. Used to buildqueries which aggregate against multiple fields and/or multipleaggregate functions. If you only need to aggregate against one field with one function, and you don&rsquo;t need to use groupBy(), then use one of the terminal functions instead:
<code>avg()</code>
<code>min()</code>
<code>max()</code>
<code>count()</code></p>
<h5 id="parameters-15">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>aggregateType</td>
          <td>Aggregate type (&lsquo;sum&rsquo;, &lsquo;avg&rsquo;, &lsquo;min&rsquo;, &lsquo;max&rsquo;, or &lsquo;count&rsquo;)</td>
      </tr>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Field to aggregate</td>
      </tr>
  </tbody>
</table>
<h5 id="example-18">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">aggregate</span><span class="p">(</span><span class="s1">&#39;avg&#39;</span><span class="p">,</span> <span class="s1">&#39;reassignment_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">groupBy</span><span class="p">(</span><span class="s1">&#39;contact_type&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">select</span><span class="p">();</span>
</span></span></code></pre></div><hr>
<h4 id="having">having()</h4>
<p>Filters aggregate groups. Used with <code>aggregate()</code> and <code>groupBy</code>.</p>
<h5 id="parameters-16">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>String</td>
          <td>aggregateType</td>
          <td>Aggregate type (&lsquo;sum&rsquo;, &lsquo;avg&rsquo;, &lsquo;min&rsquo;, &lsquo;max&rsquo;, or &lsquo;count&rsquo;)</td>
      </tr>
      <tr>
          <td>String</td>
          <td>field</td>
          <td>Field to aggregate</td>
      </tr>
      <tr>
          <td>String</td>
          <td>operator</td>
          <td>Only numeric operators allowed: &lsquo;&gt;&rsquo;, &lsquo;&lt;&rsquo;, &lsquo;&gt;=&rsquo;, &lsquo;&lt;=&rsquo;, &lsquo;=&rsquo;, and &lsquo;!=&rsquo;</td>
      </tr>
      <tr>
          <td>number</td>
          <td>value</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h5 id="example-19">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="o">*</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;description&#39;</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">groupBy</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">aggregate</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="s1">&#39;reassignment_count&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">having</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="s1">&#39;reassignment_count&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">select</span><span class="p">()</span>
</span></span></code></pre></div><h3 id="miscellanious">Miscellanious</h3>
<h4 id="disableautosysfields">disableAutoSysFields()</h4>
<p>Returns a GlideQuery which does not update sys fields such as sys_created_on, sys_updated_on, and sys_mod_count. This is the equivalent of using autoSysFields(false) with GlideRecord.</p>
<h5 id="example-20">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">disableAutoSysFields</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">insert</span><span class="p">({</span> <span class="nx">description</span><span class="o">:</span> <span class="s1">&#39;example&#39;</span><span class="p">,</span> <span class="nx">priority</span><span class="o">:</span> <span class="mi">1</span> <span class="p">});</span>
</span></span></code></pre></div><hr>
<h4 id="forceupdate">forceUpdate()</h4>
<p>Returns a GlideQuery which forces an update even when no changes are made. Useful when you want to force a business rule to execute.</p>
<h5 id="example-21">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;task&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">forceUpdate</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="s1">&#39;sys_id&#39;</span><span class="p">,</span> <span class="nx">taskId</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">update</span><span class="p">()</span>
</span></span></code></pre></div><hr>
<h4 id="orderby">orderBy()</h4>
<p>Returns a GlideQuery which specifies that the records should be returned in ascending order by a given field.</p>
<h5 id="example-22">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">query</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orderBy</span><span class="p">(</span><span class="s1">&#39;number&#39;</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="orderbydesc">orderByDesc()</h4>
<p>Returns a GlideQuery which specifies that the records should be returned in descending order by a given field. Can be used with aggregate queries</p>
<h5 id="example-23">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">query</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orderByDesc</span><span class="p">(</span><span class="s1">&#39;number&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">aggregate</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="s1">&#39;child_incidents&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">groupBy</span><span class="p">(</span><span class="s1">&#39;category&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orderByDesc</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="s1">&#39;child_incidents&#39;</span><span class="p">)</span>
</span></span></code></pre></div><hr>
<h4 id="limit">limit()</h4>
<p>Returns a GlideQuery which limits the number of records returned.</p>
<h5 id="parameters-17">Parameters</h5>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Name</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>[number</td>
          <td>limit max number of records to return</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h5 id="example-24">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">incidents</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;incident&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">limit</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;priority&#39;</span><span class="p">,</span> <span class="s1">&#39;description&#39;</span><span class="p">);</span>
</span></span></code></pre></div><hr>
<h4 id="withacls">withAcls()</h4>
<p>By default GlideQuery uses GlideRecord for database interactions. By calling withAcls() GlideQuery will use GlideRecordSecure, which honors ACLs.</p>
<h5 id="example-25">Example</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">users</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GlideQuery</span><span class="p">(</span><span class="s1">&#39;sys_user&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">withAcls</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">limit</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">orderByDesc</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">toArray</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
</span></span></code></pre></div><hr>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
