-
Notifications
You must be signed in to change notification settings - Fork 6
/
path-operators.html
159 lines (152 loc) · 26.2 KB
/
path-operators.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>Path Operators · JSONata</title><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta name="generator" content="Docusaurus"/><meta name="description" content="The path operators underpin the declarative nature of the map/filter/reduce processing model in JSONata."/><meta name="docsearch:version" content="2.0.0"/><meta name="docsearch:language" content="en"/><meta property="og:title" content="Path Operators · JSONata"/><meta property="og:type" content="website"/><meta property="og:url" content="http://docs.jsonata.org/"/><meta property="og:description" content="The path operators underpin the declarative nature of the map/filter/reduce processing model in JSONata."/><meta name="twitter:card" content="summary"/><link rel="shortcut icon" href="/img/jsonata-button.png"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script type="text/javascript" src="/js/jsonata-examples.js"></script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body class="sideNavVisible separateOnPageNav"><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/jsonata-button.png" alt="JSONata"/><h2 class="headerTitleWithLogo">JSONata</h2></a><a href="/versions"><h3>2.0.0</h3></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class="siteNavGroupActive"><a href="/overview" target="_self">Docs</a></li><li class=""><a href="http://try.jsonata.org" target="_self">Try</a></li><li class=""><a href="https://github.com/jsonata-js/jsonata" target="_self">GitHub</a></li><li class=""><a href="https://www.npmjs.com/package/jsonata" target="_self">NPM</a></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><div class="hamburger-menu"><div class="line1"></div><div class="line2"></div><div class="line3"></div></div></div><h2><i>›</i><span>Operators</span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle">Getting Started</h3><ul class=""><li class="navListItem"><a class="navItem" href="/overview">Overview</a></li><li class="navListItem"><a class="navItem" href="/using-nodejs">In NodeJS</a></li><li class="navListItem"><a class="navItem" href="/using-browser">In a Web Page</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Language Guide</h3><ul class=""><li class="navListItem"><a class="navItem" href="/simple">Simple Queries</a></li><li class="navListItem"><a class="navItem" href="/predicate">Predicate Queries</a></li><li class="navListItem"><a class="navItem" href="/expressions">Functions and Expressions</a></li><li class="navListItem"><a class="navItem" href="/construction">Result Structures</a></li><li class="navListItem"><a class="navItem" href="/composition">Query Composition</a></li><li class="navListItem"><a class="navItem" href="/sorting-grouping">Sorting, Grouping and Aggregation</a></li><li class="navListItem"><a class="navItem" href="/processing">Processing Model</a></li><li class="navListItem"><a class="navItem" href="/programming">Functional Programming</a></li><li class="navListItem"><a class="navItem" href="/regex">Regular Expressions</a></li><li class="navListItem"><a class="navItem" href="/date-time">Date/Time Processing</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Operators</h3><ul class=""><li class="navListItem navListItemActive"><a class="navItem" href="/path-operators">Path Operators</a></li><li class="navListItem"><a class="navItem" href="/numeric-operators">Numeric Operators</a></li><li class="navListItem"><a class="navItem" href="/comparison-operators">Comparison Operators</a></li><li class="navListItem"><a class="navItem" href="/boolean-operators">Boolean Operators</a></li><li class="navListItem"><a class="navItem" href="/other-operators">Other Operators</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Function Library</h3><ul class=""><li class="navListItem"><a class="navItem" href="/string-functions">String Functions</a></li><li class="navListItem"><a class="navItem" href="/numeric-functions">Numeric Functions</a></li><li class="navListItem"><a class="navItem" href="/aggregation-functions">Aggregation Functions</a></li><li class="navListItem"><a class="navItem" href="/boolean-functions">Boolean Functions</a></li><li class="navListItem"><a class="navItem" href="/array-functions">Array Functions</a></li><li class="navListItem"><a class="navItem" href="/object-functions">Object Functions</a></li><li class="navListItem"><a class="navItem" href="/date-time-functions">Date/Time Functions</a></li><li class="navListItem"><a class="navItem" href="/higher-order-functions">Higher Order Functions</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Extending JSONata</h3><ul class=""><li class="navListItem"><a class="navItem" href="/embedding-extending">Embedding and Extending JSONata</a></li><li class="navListItem"><a class="navItem" href="/contributing">Community and Contributing</a></li></ul></div></div></section></div><script>
var coll = document.getElementsByClassName('collapsible');
var checkActiveCategory = true;
for (var i = 0; i < coll.length; i++) {
var links = coll[i].nextElementSibling.getElementsByTagName('*');
if (checkActiveCategory){
for (var j = 0; j < links.length; j++) {
if (links[j].classList.contains('navListItemActive')){
coll[i].nextElementSibling.classList.toggle('hide');
coll[i].childNodes[1].classList.toggle('rotate');
checkActiveCategory = false;
break;
}
}
}
coll[i].addEventListener('click', function() {
var arrow = this.childNodes[1];
arrow.classList.toggle('rotate');
var content = this.nextElementSibling;
content.classList.toggle('hide');
});
}
document.addEventListener('DOMContentLoaded', function() {
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
createToggler('#tocToggler', 'body', 'tocActive');
var headings = document.querySelector('.toc-headings');
headings && headings.addEventListener('click', function(event) {
var el = event.target;
while(el !== headings){
if (el.tagName === 'A') {
document.body.classList.remove('tocActive');
break;
} else{
el = el.parentNode;
}
}
}, false);
function createToggler(togglerSelector, targetSelector, className) {
var toggler = document.querySelector(togglerSelector);
var target = document.querySelector(targetSelector);
if (!toggler) {
return;
}
toggler.onclick = function(event) {
event.preventDefault();
target.classList.toggle(className);
};
}
});
</script></nav></div><div class="container mainContainer docsContainer"><div class="wrapper"><div class="post"><header class="postHeader"><a class="edit-page-link button" href="https://github.com/jsonata-js/jsonata/edit/master/docs/path-operators.md" target="_blank" rel="noreferrer noopener">Edit</a><h1 id="__docusaurus" class="postHeaderTitle">Path Operators</h1></header><article><div><span><p>The path operators underpin the declarative nature of the map/filter/reduce processing model in JSONata.</p>
<h2><a class="anchor" aria-hidden="true" id="-map"></a><a href="#-map" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>.</code> (Map)</h2>
<p>The dot operator is one of the fundamental building blocks in JSONata expressions. It implements the 'for each' or 'map' function that is common in many functional languages.</p>
<p>The dot operator performs the following logic:</p>
<ul>
<li>The expression on the LHS is evaluated to produce an array of values.
<ul>
<li>If it evaluates to a single value, that is treated as equivalent to an array containing that single value</li>
<li>If it evaluates to nothing (no match or empty array), then the result of the operator expression is nothing</li>
</ul></li>
<li>For each value in the LHS array in turn:
<ul>
<li>The value is known as the <em>context</em> and is used as the basis for any relative path expression on the RHS. It is also accessible in the RHS expression using the <code>$</code> symbol.</li>
<li>The RHS expression is evaluated to produce a value or array of values (or nothing). These values are appended to a combined array of results for the operator as a whole.</li>
</ul></li>
<li>The combined result of the operator is returned.</li>
</ul>
<p>This operator is left associative meaning that the expression <code>a.b.c.d</code> is evaluated like <code>((a.b).c).d</code>; i.e. left to right</p>
<p><strong>Examples</strong></p>
<ul>
<li><code>Address.City</code> => <code>"Winchester"</code></li>
<li><code>Phone.number</code> => <code>[ "0203 544 1234", "01962 001234", "01962 001235", "077 7700 1234" ]</code></li>
<li><code>Account.Order.Product.(Price * Quantity)</code> => <code>[ 68.9, 21.67, 137.8, 107.99 ]</code></li>
<li><code>Account.Order.OrderID.$uppercase()</code> => <code>[ "ORDER103", "ORDER104"]</code></li>
</ul>
<h2><a class="anchor" aria-hidden="true" id="---filter"></a><a href="#---filter" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>[</code> ... <code>]</code> (Filter)</h2>
<p>The filter operator (a.k.a predicate) is used to select only the items in the input sequence that satisfy the predicate expression contained between the square brackets.</p>
<p>If the predicate expression is an integer, or an expression that evaluates to an integer, then the item at that position (zero offset) in the input sequence is the only item selected for the result sequence.
If the number is non-integer, then it is rounded <em>down</em> to the nearest integer.</p>
<p>If the predicate expression is an array of integers, or an expression that evaluates to an array of integers, then the items at those positions (zero offset) in the input sequence is the only item selected for the result sequence.</p>
<p>If the predicate expression evaluates to any other value, then it is cast to a Boolean as if using the <code>$boolean()</code> function. If this evaluates to <code>true</code>, then the item is retained in the result sequence. Otherwise it is rejected.</p>
<p>See <a href="simple#navigating-json-arrays">Navigating JSON Arrays</a> and <a href="predicate">Predicates</a> for more details and examples.</p>
<h2><a class="anchor" aria-hidden="true" id="---order-by"></a><a href="#---order-by" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>^(</code> ... <code>)</code> (Order-by)</h2>
<p>The order-by operator is used to sort an array of values into ascending or descending order according to one or more expressions defined within the parentheses.</p>
<p>By default, the array will be sorted into ascending order. For example:</p>
<p><code>Account.Order.Product^(Price)</code></p>
<p>sorts all of the products into order of increasing price (<code>Price</code> is a numeric field in the <code>Product</code> object).</p>
<p>To sort in descending order, the sort expression must be preceded by the <code>></code> symbol. For example:</p>
<p><code>Account.Order.Product^(>Price)</code></p>
<p>sorts all of the products into order of decreasing price. The <code><</code> symbol can be used to explicitly indicate ascending order, although that is the default behaviour.</p>
<p>Secondary (and more) sort expressions can be specified by separating them with commas (<code>,</code>). The secondary expression will be used to determine order if the primary expression ranks two values the same. For example,</p>
<p><code>Account.Order.Product^(>Price, <Quantity)</code></p>
<p>orders the products primarily by decreasing price, but for products of the same price, by increasing quantity.</p>
<p>The sort expression(s) can be any valid JSONata expression that evaluates to a number or a string. If it evaluates to a string then the array is sorted in order of unicode codepoint.</p>
<p><strong>Examples</strong></p>
<ul>
<li><code>Account.Order.Product^(Price * Quantity)</code> => Increasing order of price times quantity.</li>
<li><code>student[type='fulltime']^(DoB).name</code> => The names of all full time students sorted by date of birth (the DoB value is an ISO 8601 date format)</li>
</ul>
<h2><a class="anchor" aria-hidden="true" id="---reduce"></a><a href="#---reduce" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>{</code> ... <code>}</code> (Reduce)</h2>
<p>The reduce operator can be used as the last step in a path expression to group and aggregate its input sequence into a single object.
The key/value pairs between the curly braces determine the groupings (by evaluating the key expression) and the aggregated values for each group.
See <a href="sorting-grouping#grouping">Grouping and Aggregation</a> for more details.</p>
<h2><a class="anchor" aria-hidden="true" id="-wildcard"></a><a href="#-wildcard" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>*</code> (Wildcard)</h2>
<p>This wildcard selects the values of all the properties of the context object. It can be used in a path expression in place of a property name, but it cannot be combined with other characters like a glob pattern. The order of these values in the result sequence is implementation dependent.
See <a href="predicate#wildcards">Wildcards</a> for examples.</p>
<h2><a class="anchor" aria-hidden="true" id="-descendants"></a><a href="#-descendants" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>**</code> (Descendants)</h2>
<p>This wildcard recursively selects the values of all the properties of the context object, and the properties of any objects contained within these values as it descends the hierarchy.
See <a href="predicate#navigate-arbitrary-depths">Navigate arbitrary depths</a>.</p>
<h2><a class="anchor" aria-hidden="true" id="-parent"></a><a href="#-parent" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>%</code> (Parent)</h2>
<p>This will select the 'parent' of the current context value. Here, we define 'parent' to be the enclosing object which has the property representing the context value.</p>
<p>This is the only operation which searches 'backwards' in the input data structure. It is implemented by static analysis of the expression at <a href="https://docs.jsonata.org/embedding-extending#jsonatastr">compile time</a> and can only be used within expressions that navigate through that target parent value in the first place.
If, for any reason, the parent location cannot be determined, then a static error (S0217) is thrown.</p>
<p><strong>Example</strong></p>
<pre><code class="hljs"><span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Account</span>.</span><span class="hljs-module"><span class="hljs-identifier">Order</span>.</span><span class="hljs-module"><span class="hljs-identifier">Product</span>.</span>{
'<span class="hljs-module"><span class="hljs-identifier">Product</span>'</span>: `<span class="hljs-module"><span class="hljs-identifier">Product</span> </span><span class="hljs-module"><span class="hljs-identifier">Name</span>`</span>,
'<span class="hljs-module"><span class="hljs-identifier">Order</span>'</span>: %.<span class="hljs-module"><span class="hljs-identifier">OrderID</span>,</span>
'<span class="hljs-module"><span class="hljs-identifier">Account</span>'</span>: %.%.`<span class="hljs-module"><span class="hljs-identifier">Account</span> </span><span class="hljs-module"><span class="hljs-identifier">Name</span>`</span>
}</span>
</code></pre>
<p>This returns an array of objects for each product in each order in each account. Information from the enclosing Order and Account objects can be accessed using the parent operator.
The repeated combination of <code>%.%.</code> is used to access the grandparent and higher ancestors.</p>
<h2><a class="anchor" aria-hidden="true" id="-positional-variable-binding"></a><a href="#-positional-variable-binding" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>#</code> (Positional variable binding)</h2>
<p>This can be used to determine at which position in the sequence the current context item is. It can be used following any map, filter or order-by stage in the path.
The variable is available for use within subsequent stages of the path (e.g. within filter predicates) and goes out of scope at the end of the path expression.</p>
<p><strong>Example</strong></p>
<pre><code class="hljs">library.books<span class="hljs-meta">#$i[<span class="hljs-string">'Kernighan'</span> in authors].{</span>
<span class="hljs-string">'title'</span>: title,
<span class="hljs-string">'index'</span>: $i
}
</code></pre>
<p>This returns an array of objects for each book in the library where Kernighan is one of the authors. Each object contains the book's title and its position within the books array before it was filtered.</p>
<h2><a class="anchor" aria-hidden="true" id="-context-variable-binding"></a><a href="#-context-variable-binding" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>@</code> (Context variable binding)</h2>
<p>This is used to bind the current context item (<code>$</code>) to a named variable. It can only be used directly following a map stage, not a filter or order-by stage.
The variable binding remains in scope for the remainder of the path expression.</p>
<p>Because the current context has now been explicitly bound to a named variable, this context will be carried forward to be the context of the next stage in the path.
For example, in this snippet of a path, <code>library.loans@$l.books</code>, the loans array is a property of the library object and each loan will, in turn, be bound to the variable <code>$l</code>.
The books array, which is also a property of the library object, will then be selected.</p>
<p>This operator can be used to perform data joins within a path because of its ability to do cross-referencing across objects.</p>
<p><strong>Example</strong></p>
<pre><code class="hljs">library.loans@<span class="hljs-variable">$l</span>.books@<span class="hljs-variable">$b</span>[<span class="hljs-variable">$l</span>.<span class="hljs-attribute">isbn</span>=<span class="hljs-variable">$b</span>.isbn].{
<span class="hljs-string">'title'</span>: <span class="hljs-variable">$b</span>.title,
<span class="hljs-string">'customer'</span>: <span class="hljs-variable">$l</span>.customer
}
</code></pre>
<p>This performs an 'inner join' between objects in the loans array and objects in the books array where the ISBNs match between the structures.</p>
<p>Block expressions can be used to widen the scope of the data cross-referencing as shown in this example:</p>
<pre><code class="hljs">(library.loans)@<span class="hljs-variable">$l</span>.(catalog.books)@<span class="hljs-variable">$b</span>[<span class="hljs-variable">$l</span>.<span class="hljs-attribute">isbn</span>=<span class="hljs-variable">$b</span>.isbn].{
<span class="hljs-string">'title'</span>: <span class="hljs-variable">$b</span>.title,
<span class="hljs-string">'customer'</span>: <span class="hljs-variable">$l</span>.customer
}
</code></pre>
</span></div></article></div><div class="docs-prevnext"><a class="docs-prev button" href="/date-time"><span class="arrow-prev">← </span><span>Date/Time Processing</span></a><a class="docs-next button" href="/numeric-operators"><span>Numeric Operators</span><span class="arrow-next"> →</span></a></div></div></div><nav class="onPageNav"><ul class="toc-headings"><li><a href="#-map"><code>.</code> (Map)</a></li><li><a href="#---filter"><code>[</code> ... <code>]</code> (Filter)</a></li><li><a href="#---order-by"><code>^(</code> ... <code>)</code> (Order-by)</a></li><li><a href="#---reduce"><code>{</code> ... <code>}</code> (Reduce)</a></li><li><a href="#-wildcard"><code>*</code> (Wildcard)</a></li><li><a href="#-descendants"><code>**</code> (Descendants)</a></li><li><a href="#-parent"><code>%</code> (Parent)</a></li><li><a href="#-positional-variable-binding"><code>#</code> (Positional variable binding)</a></li><li><a href="#-context-variable-binding"><code>@</code> (Context variable binding)</a></li></ul></nav></div><footer class="nav-footer" id="footer"><section class="sitemap"><a href="/" class="nav-home"><img src="/img/jsonata-white-167.png" alt="JSONata"/></a><div><h5>JSONata</h5><a href="http://jsonata.org" target="_blank" rel="noreferrer noopener">JSON query and<br/>transformation language</a><a href="http://try.jsonata.org" target="_blank" rel="noreferrer noopener">Go play in the<br/>JSONata Exerciser</a></div><div><h5>Community</h5><a href="https://stackoverflow.com/questions/tagged/jsonata" target="_blank" rel="noreferrer noopener">Stack Overflow</a><a href="https://jsonata.slack.com/">Project Chat</a><a href="https://twitter.com/" target="_blank" rel="noreferrer noopener">Twitter</a></div><div><h5>More</h5><a href="https://github.com/jsonata-js/jsonata">GitHub</a><a class="github-button" href="https://github.com/jsonata-js/jsonata" data-icon="octicon-star" data-count-href="/jsonata-js/jsonata/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star this project on GitHub">Star</a></div></section><section class="copyright">Copyright © 2021 JSONata.org</section></footer></div></body></html>