<rss version="2.0">
  <channel>
    <title>Joel Abrahamsson</title>
    <description>Joel Abrahamsson</description>
    <link>http://joelabrahamsson.com/rss</link>
    <item>
      <title>Why is the async keyword needed in JavaScript?</title>
      <description>Last week a colleague asked me what the purpose of the async keyword was in JavaScript. Not because he didn't know how to use async/await. He was wondering why the async keyword was needed to use await. This set me off on a quest to find the answer. To avoid beating around the bush: its purpose is backwards compatibility.
&lt;p&gt;Any experienced JavaScript developer is probably well versed in the usage of async/await these days. The &lt;span class="code-concept"&gt;await&lt;/span&gt; keyword unwraps a &lt;span class="code-concept"&gt;Promise&lt;/span&gt;. Until the &lt;span class="code-concept"&gt;Promise&lt;/span&gt; is either fulfilled or rejected the execution of the code after it is put on hold and the event loop is released to do other work. But why is the &lt;span class="code-concept"&gt;async&lt;/span&gt; keyword needed in order for us to use &lt;span class="code-concept"&gt;await&lt;/span&gt; in a function?&lt;/p&gt;
&lt;p&gt;A common misconception seems to be that it "is used to communicate that the function is async" to anyone who uses it. However, that's not true. Consider the following code:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;export async function fetchTextLength() {&lt;br /&gt; const resp = await fetch("https://www.wikipedia.org");&lt;br /&gt; const text = await resp.text();&lt;br /&gt; return text.length;&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;The function above is marked async, but as a consumer of it that's hardly relevant. What is relevant is that it returns a &lt;span class="code-concept"&gt;Promise&lt;/span&gt;. Indeed, if we hover over it in a file that uses it in VS Code that's what we see:&lt;/p&gt;
&lt;p&gt;&lt;img class="thumbnail-centered" src="/PageFiles/741/vscode-promise.png" alt="" width="1031" height="208" /&gt;&lt;/p&gt;
&lt;p&gt;Further, I think we can all agree that to a consumer of the above module it shouldn't matter if we decide to change the module to instead have the following implementation:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;export function fetchTextLength() {
    return inner();
}

async function inner() {
    const resp = await fetch("https://www.wikipedia.org");
    const text = await resp.text();return text.length;
}&lt;/pre&gt;
&lt;p&gt;The important thing is that our function returns a &lt;span class="code-concept"&gt;Promise&lt;/span&gt;, not whether it's marked as &lt;span class="code-concept"&gt;async&lt;/span&gt;&amp;nbsp;or not. So, if the purpose of the &lt;span class="code-concept"&gt;async&lt;/span&gt;&amp;nbsp;keyword isn't to communicate anything to other developers then what's its purpose? One could think that it's being used by the JavaScript interpreter (or JIT compiler) to identify that the function is using &lt;span class="code-concept"&gt;await&lt;/span&gt; and to do its thing, implicitly having the function return a &lt;span class="code-concept"&gt;Promise&lt;/span&gt;. While that's true the interpreter could easily do that simply by looking at the code and identifying usage of the &lt;span class="code-concept"&gt;await&lt;/span&gt;&amp;nbsp;keyword.&lt;/p&gt;
&lt;p&gt;The real motivation for the &lt;span class="code-concept"&gt;async&lt;/span&gt; keyword can be found by digging through &lt;a href="https://github.com/tc39/proposal-async-await"&gt;the original proposal&lt;/a&gt; for async/await in ECMAScript. There in a comment by Brian Terlson &lt;a href="https://github.com/tc39/proposal-async-await/issues/88#issuecomment-181578920"&gt;in issue 88&lt;/a&gt; we can read the following:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;"Long ago we considered whether it was possible to await everywhere but we could not find a good way to do it without breaking existing usage of await as an identifier"&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In other words, with the introduction of &lt;span class="code-concept"&gt;await&lt;/span&gt; in ECMAScript a new reserved keyword needed to be added to the language. However, you can't just go around adding reserved keywords to programming languages if you want to be compatible with existing code. This is especially true for interpreted ones run in browsers. So the &lt;span class="code-concept"&gt;async&lt;/span&gt; keyword was introduced as a way to ensure backwards compatibility.&lt;/p&gt;
&lt;p&gt;To illustrate, the below code is perfectly valid and outputs "test":&lt;/p&gt;
&lt;pre class="prettyprint"&gt;function test() {
    const await = "test";
    console.log(await);
}

test();&lt;/pre&gt;
&lt;p&gt;However, if we add the &lt;span class="code-concept"&gt;async&lt;/span&gt; keyword, which would not have been valid in older versions of JS, to the function like below we'll get an error when we try to run it:&lt;/p&gt;
&lt;pre&gt;async function test() {
    const await = "test";
    console.log(await);
}

test();&lt;/pre&gt;
&lt;p&gt;The above code produces:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;const await = "test";
        ^^^^^

SyntaxError: Unexpected reserved word&lt;/pre&gt;
</description>
      <link>http://joelabrahamsson.com/why-is-the-async-keyword-needed-in-javascript/</link>
      <guid>http://joelabrahamsson.com/why-is-the-async-keyword-needed-in-javascript/</guid>
      <pubDate>Mon, 11 Sep 2023 21:02:57 +0100</pubDate>
      <category>Programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Exception order when awaiting multiple async tasks in C#</title>
      <description>A C# has-been returns to C# and experiments with this new hip thing called async/await and how that relates to execution order and exceptions.
&lt;p&gt;I recently returned to .NET and C# development after a six year hiatus in Node.JS land. A lot has changed since I last wrote C#, although Jon Skeet still writes the best books.&lt;/p&gt;
&lt;p&gt;One feature that I never got to use during my previous C# development days were async/await. However, I'm very familiar with the concept having written a lot of JavaScript with promises and async/await. However, one thing that I didn't intuitively knew in C# was in what order Exceptions are thrown, or rather caught, when awaiting multiple Tasks. Therefor I created this little experiment:&amp;nbsp;&lt;/p&gt;
&lt;pre class="prettyprint"&gt;using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncExceptions
{
  class Program
  {
    async static Task Main(string[] args)
    {
      try
      {
        var one = Do("One", 500);
        var two = Do("Two", 500);

        await one;
        await two;
       } catch(Exception ex)
       {
          Console.WriteLine(ex.Message);
        }
           
      }
      
      public static Task Do(string name, int time)
      {
        return Task.Run(() =&amp;gt;
        {
          Console.WriteLine($"Task {name} starting");
          Thread.Sleep(time);
          Console.WriteLine($"Task {name} pre exception");
          throw new Exception($"Exception {name}");
        });
      }
  }
}
&lt;/pre&gt;
&lt;p class="conclusion"&gt;Note: This is a contrived example that intrigues me and which we are exploring in this article. In practice you shouldn’t write code like the one above, with two separate awaits but instead use &lt;span class="code-concept"&gt;Task.WhenAll()&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The above program will output five lines in total. Two lines will be printed for when each task starts to run. Two additional lines will be outputted when each task has waited for 500 milliseconds and is about to throw. Finally there will be a line telling us which exception was caught. Can you guess what the output will be?&lt;/p&gt;
&lt;p&gt;As it turned out in my experiments the first four lines are quite random. Sometimes the first tasks starts and completes first, sometimes it's the other way around. Here are three sample outputs (the final line omitted for now):&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sample 1:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="prettyprint"&gt;Task One starting
Task Two starting
Task Two pre exception
Task One pre exception&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Sample 2:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="prettyprint"&gt;Task One starting
Task Two starting
Task One pre exception&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Sample 3:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="prettyprint"&gt;Task Two starting
Task One starting
Task Two pre exception
Task One pre exception&lt;/pre&gt;
&lt;p&gt;What about the final line? That's always reads `Exception One`. Meaning that although the second exception may sometimes be thrown first in the async context back in our main thread we'll always catch the exception from the task that we await first. That holds true even if we make the second task throw much sooner by modifying the Main method to look like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;var one = Do("One", 500);
var two = Do("Two", 1);&lt;/pre&gt;
&lt;p&gt;Of course in hindsight of this experiment the result makes sense. While the second async operation may complete and be ready to return to the initiating thread first in that thread we are waiting for the first task to complete before caring about the result of the second one.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;JavaScript&lt;/h2&gt;
&lt;p&gt;So what about the equivalent code i JavaScript? It could look something like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;"use strict";

async function main() {
    try {
        const one = Do("One", 500);
        const two = Do("Two", 500);

        await one;
        await two; 
    } catch(ex) {
        console.log(ex.message)
    }
}

main();

function Do(name, time) {
    return new Promise((resolve, reject) =&amp;gt; {
        console.log(`Task ${name} starting`)
        setTimeout(() =&amp;gt; {
            console.log(`Task ${name} pre exception`);
            reject(new Error(`Exception ${name}`))
        }, time);
    })
    
}&lt;/pre&gt;
&lt;p class="conclusion"&gt;Note: Again this is a contrived example. In practice you should use &lt;span class="code-concept"&gt;Promise.all()&lt;/span&gt; in code like this.&lt;/p&gt;
&lt;p&gt;Here the output is more consistent. In all my attempts the output read like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;Task One starting
Task Two starting
Task One pre exception
Task Two pre exception
Exception One
(node:6564) UnhandledPromiseRejectionWarning: Error: Exception Two&lt;/pre&gt;
&lt;p&gt;The first task is put queue for execution on the event loop first and therefor is executed and throws first. We catch the first exception and then get an angry error message due to us not catching the second exception. Clearly Promise.all would be a good solution for that.&lt;/p&gt;
&lt;p&gt;But what if we change the second task to complete much faster than the first one?&lt;/p&gt;
&lt;pre class="prettyprint"&gt;const one = Do("One", 500);
const two = Do("Two", 1);&lt;/pre&gt;
&lt;p&gt;Then the output is this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;Task One starting
Task Two starting
Task Two pre exception
(node:6577) UnhandledPromiseRejectionWarning: Error: Exception Two
Task One pre exception
Exception One&lt;/pre&gt;
&lt;p&gt;The second task throws much earlier and that results in a an&amp;nbsp;UnhandledPromiseRejectionWarning. Then the execution continues and the exception thrown by the first, and first awaited, task is caught.&amp;nbsp;While I find this fascinating I think I'll leave the "why!?" to a different blog post.&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/exception-order-when-awaiting-multiple-async-tasks-in-c/</link>
      <guid>http://joelabrahamsson.com/exception-order-when-awaiting-multiple-async-tasks-in-c/</guid>
      <pubDate>Mon, 09 Sep 2019 22:30:06 +0100</pubDate>
      <category>Programming</category>
      <category>C#</category>
      <category>code samples</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Flatten array of arrays with JavaScript</title>
      <description>&lt;pre class="prettyprint"&gt;const arrays = [[1], ["2"], [3]];&lt;br /&gt;&lt;br /&gt;const merged = [].concat(...arrays);&lt;br /&gt;&lt;br /&gt;console.log(merged); //&amp;nbsp;&lt;span class="s1"&gt;[ &lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="s1"&gt; ]&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Pre ES6:&lt;/p&gt;
&lt;pre class="default prettyprint prettyprinted"&gt;&lt;code&gt;&lt;span class="pln"&gt;var merged &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[].&lt;/span&gt;&lt;span class="pln"&gt;concat&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;apply&lt;/span&gt;&lt;span class="pun"&gt;([],&lt;/span&gt;&lt;span class="pln"&gt; arrays&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>http://joelabrahamsson.com/flatten-array-of-arrays-with-javascript/</link>
      <guid>http://joelabrahamsson.com/flatten-array-of-arrays-with-javascript/</guid>
      <pubDate>Thu, 30 Aug 2018 18:46:11 +0100</pubDate>
      <category>Programming</category>
    </item>
    <item>
      <title>Quickly mapping an array of URLs to responses with JavaScript async/await and Promise.all</title>
      <description>&lt;p&gt;While perhaps not the most readable, a compact version (using window.fetch) can look like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;const urls = [&lt;br /&gt;  "https://jsonplaceholder.typicode.com/comments/1",&lt;br /&gt;  "https://jsonplaceholder.typicode.com/comments/2",&lt;br /&gt;  "https://jsonplaceholder.typicode.com/comments/3"&lt;br /&gt;];&lt;br /&gt;
async function fetchAll() {&lt;br /&gt;  const results = await Promise.all(urls.map((url) =&amp;gt; fetch(url).then((r) =&amp;gt; r.json())));&lt;br /&gt;  console.log(JSON.stringify(results, null, 2));&lt;br /&gt;}&lt;br /&gt;
fetchAll();&lt;/pre&gt;
</description>
      <link>http://joelabrahamsson.com/quickly-mapping-an-array-of-urls-to-responses-with-javascript-asyncawait-and-promiseall/</link>
      <guid>http://joelabrahamsson.com/quickly-mapping-an-array-of-urls-to-responses-with-javascript-asyncawait-and-promiseall/</guid>
      <pubDate>Sun, 26 Aug 2018 19:09:00 +0100</pubDate>
      <category>Programming</category>
    </item>
    <item>
      <title>Quickly creating and mapping an array in JavaScript</title>
      <description>&lt;p&gt;When, for instance, creating test data one might do something like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;const data = [];&lt;/pre&gt;
&lt;pre class="prettyprint"&gt;for(let i = 0; i &amp;lt; 100; i++) {&lt;br /&gt; data.push({ num: i }); &lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;This may be written slightly shorter and more wrist friendly using Array.fill:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;const data = Array(100).fill(null).map((val, i) =&amp;gt; {&lt;br /&gt; return { num: i };&lt;br /&gt;});&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/quickly-creating-and-mapping-an-array-in-javascript/</link>
      <guid>http://joelabrahamsson.com/quickly-creating-and-mapping-an-array-in-javascript/</guid>
      <pubDate>Thu, 23 Aug 2018 20:50:25 +0100</pubDate>
      <category>Programming</category>
    </item>
    <item>
      <title>Responsibly Responsive Web Design at Expressen</title>
      <description>When building a new version of the news site Expressen.se the team hesitated to use responsive web design. Here's why and what we ended up doing.
&lt;p&gt;&lt;a href="https://www.expressen.se/"&gt;Expressen.se&lt;/a&gt; is the second largest news site in the Nordic region with millions of page views per day. During the fall of 2017 we set out to rebuild the site from scratch with a focus on building as fast a site as possible. You can read more about how and why we did this in Simon Hjälmefjord's &lt;a href="https://utveckling.expressen.se/blogg/sa-byggde-vi-nya-expressen-se-snabbare-an-nagonsin-del-1/"&gt;blog post&lt;/a&gt; (in Swedish).&lt;/p&gt;
&lt;p&gt;Another objective that we had when building the new version of the site was to end up with a single code base for the site. Prior to the rebuild we had different versions of the site for different channel and these were distributed over multiple applications. More specifically we had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A fixed width version for computers.&lt;/li&gt;
&lt;li&gt;A partially responsive version for tablets.&lt;/li&gt;
&lt;li&gt;A fluid version for smart phones.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first two of the above versions were served by one application, Ariel. Ariel naturally had functionality to handle the fact that it was serving two versions, including channel specific templates. The third version above, the mobile site, was served by a different application.&lt;/p&gt;
&lt;p&gt;This division of labor was not without benefits. We could optimize for each channel's unique&amp;nbsp;pre-requisites as well as perform experiments on subsets of the total traffic and code base. However, the fact that we had three different versions scattered across two code bases also brought some obvious drawbacks. The two code bases diverged heavily from day one and most developers tended to only know one of them well. It was also difficult to maintain a coherent user experience and design across the different channels.&lt;/p&gt;
&lt;p&gt;Another problem was that we quite often implemented new functionality for only one of the channels. That wasn't necessarily always a bad thing as the functionality may only make sense for one type of device. In other cases it would make sense for all channels but we decided to test it on a single channel first. However, sometimes we really meant to, and/or wanted to, have the new functionality in all channels but after having built it for a single channel and having spent some time measuring its impact it we had moved on to other features and it was never implemented for the remaining channels.&lt;/p&gt;
&lt;p&gt;So, when we were about to rebuild the site the entire team was very much in agreement that we wanted a single code base for the site. However, while we had no doubts about wanting a single code base for all channels, we were a lot less convinced about how to accomplish that. Should we build an application that could handle three different channels, with separate views etc., or should we build a responsive site?&lt;/p&gt;
&lt;h2&gt;It's the 21st century; of course we should build a responsive site! Shouldn't we?&lt;/h2&gt;
&lt;p&gt;These days it seems like a non-question whether to use responsive web design or not. Responsive web design has become the de facto standard and all of our competitors had already built responsive sites. However, we wanted to build the best and fastest site possible and asked ourselves the question: is responsive web design &lt;em&gt;really&lt;/em&gt; the best for us?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Responsive web design, implemented using media queries etc., brings a number of significant advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coherent design across all device types and screen sizes is the default and lapses from that require conscious decisions.&lt;/li&gt;
&lt;li&gt;A single code base for all channels is obvious and more or less a requirement.&lt;/li&gt;
&lt;li&gt;Compared to designing, developing and maintaining separate versions for different channels building a responsive site is cost efficient.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While the above advantages are significant it's interesting to note that none of them have any direct positive impact on the end users experience. For the end user there are few benefits associated with visiting a responsive site.&lt;/p&gt;
&lt;p&gt;On the other hand there are (often) drawbacks in the form of additional HTML markup, CSS and JavaScript that the visitor's browser has to download, parse and interpret. Sometimes there are entire blocks of HTML and CSS which are never even shown to the user. There may also be custom JavaScript code and modules that are only relevant in a specific channel or which are there specifically to manage the responsive nature of the site.&lt;/p&gt;
&lt;p&gt;In other words: to build a responsive site means taking the risk of serving a slower site to the end user compared to a site which is optimized for the user's device type. It's quite obvious really; when we build a responsive site we force the user's browser to deal with the problem of adapting the content depending on device and viewport witdh as well as using different layouts in different contexts.&lt;/p&gt;
&lt;p&gt;There are of course various creative ways of minimizing the performance impact but the end result tends to be less than perfect. At the same time some of the cost efficiency benefits of building a responsive site tends to get lost when we spend time on optimizing the performance of the site.&lt;/p&gt;
&lt;h2&gt;Having the cake while eating it too&lt;/h2&gt;
&lt;p&gt;So, what should we do? We wanted the development related benefits of building a responsive site without the performance penalties for our visitors. Therefore we decided to try to have the cake while eating it too. We decided to try an approach that we came to call "responsibly responsive".&lt;/p&gt;
&lt;p&gt;When I as a developer run the site on my local machine or when a UX designer views the site on a test environment what we see is a responsive site. When we design and develop we work with a responsive site.&lt;/p&gt;
&lt;p&gt;&lt;img class="thumbnail-centered" src="/PageFiles/718/lokalt-1.gif" alt="" width="480" height="270" /&gt;&lt;/p&gt;
&lt;p&gt;However, when you as a public visitor load the site you only get the HTML, CSS and JavaScript that is required for your device type. Every trace of the site's responsiveness, except for code required to give you a good experience within the context of your device type, is gone.&lt;/p&gt;
&lt;p&gt;&lt;img class="thumbnail-centered" src="/PageFiles/718/publikt-2.gif" alt="" width="480" height="270" /&gt;&lt;/p&gt;
&lt;p&gt;This way we achieve exactly what we want; the many development related benefits of building a responsive site at the same time as our visitors get a performance optimized experience tailored for the type of device that they are using.&lt;/p&gt;
&lt;h2&gt;The solution&lt;/h2&gt;
&lt;p&gt;In order to build a responsive site where all traces of it's responsive nature are cleaned out when it faces public visitors we had to tackle a number of problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Channel detection&lt;/li&gt;
&lt;li&gt;Filtering of HTML&lt;/li&gt;
&lt;li&gt;Filtering of CSS&lt;/li&gt;
&lt;li&gt;Filtering of JavaScript&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Channel detection&lt;/h3&gt;
&lt;p&gt;In order to detect what channel a visitor is in we're using device detection in our CDN (Akamai). When a visitor navigates to www.expressen.se the request is routed to Akamai, which inspects the request's user agent and determines whether the user is using a mobile phone, a tablet or a computer. If Akamai doesn't already have the appropriate version of the content in its cache it proceeds to make a request to our servers. This request contains a header telling our servers what type of device the original request was made from.&lt;/p&gt;
&lt;p&gt;If our application finds that header in an incoming request it knows that it should serve a version of the site optimized for the device type specified in the header. If on the other hand a request doesn't contain the header our application knows that the request isn't external and will proceed to serve the responsive version of the site.&lt;/p&gt;
&lt;p&gt;Using a CDN for device detection is convenient for us but by no means a requirement. If we hadn't been using a CDN or other form of caching layer outside our application we could have implemented the same functionality in our app by inspecting each request's&amp;nbsp; user agent.&lt;/p&gt;
&lt;h3&gt;HTML filtering&lt;/h3&gt;
&lt;p&gt;When building a responsive site one can choose between two different approaches for handling how elements should be displayed depending on view port size in HTML and CSS. With the first approach, which is often preferable, the HTML markup doesn't know that it's responsive and instead lets the CSS handle how elements should be positioned and look depending on screen size etc. In the other approach, which Twitter's Bootstrap is an example of, one uses helper CSS classes in the HTML markup to decide whether an element should be displayed or not (or how it should be displayed) depending on browser size.&lt;/p&gt;
&lt;p&gt;If we had built a site that would be responsive when it faced public visitors we would probably have used the first method. However in our case we wanted to make it easy to clean up unnecessary HTML elements and for that the second approach, using helper classes, was better. This means that when I look at the site's HTML on my local computer, without channel filtering, a small sample of it can look like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;aside class="site-body__column-3 &lt;br /&gt; hidden-mobile lp_right"&amp;gt;&lt;br /&gt; ...&lt;br /&gt;&amp;lt;/aside&amp;gt;&lt;/pre&gt;
&lt;p&gt;When I instead browse the public version of the site using a computer or tablet the same HTML block looks like the below snippet. Note the absence of the &lt;span class="code-concept"&gt;hidden-mobile&lt;/span&gt; CSS class.&amp;nbsp;&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;aside class="site-body__column-3 &lt;br /&gt; lp_right"&amp;gt;&lt;br /&gt; ...&lt;br /&gt;&amp;lt;/aside&amp;gt;&lt;/pre&gt;
&lt;p&gt;If I make the same request using a mobile phone the entire HTML block would instead be missing.&lt;/p&gt;
&lt;p&gt;In order to accomplish this we first let our application render the responsive HTML with support for all channels and helper classes included. After that, just before the app is about to respond to the incoming HTTP request, a middleware (we use Node.JS) kicks in. The middleware inspects the incoming request and looks for a header (set by Akamai or manually by a developer) containing information about what channel is requested.&lt;/p&gt;
&lt;p&gt;If the middleware finds such a header it proceeds to pass the generated markup through a parser. The parser removes all elements that, according to helper classes, shouldn't be shown for the requested channel. The parser also removes all helper classes.&lt;/p&gt;
&lt;p&gt;Generating markup only to then parse and rebuild it may sound like an expensive operation. However, our parser, which is built on top of &lt;a href="https://www.npmjs.com/package/htmlparser2"&gt;htmlparser2&lt;/a&gt;, is simple and pretty fast and only adds a few milliseconds to the total response time. Every millisecond counts though but in practice most of our requests are served directly from our CDN's cache so only a small fraction of all requests are afflicted by the minor overhead added by the parser.&lt;/p&gt;
&lt;h3&gt;CSS filtering&lt;/h3&gt;
&lt;p&gt;We write our CSS (actually Stylus) code just as we would have if we would have been working on a regular responsive site with one small exception; in cases where we need to use media queries to adapt for different device types and view port sizes we always do that using helper functions. A fictive example may look like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;.myElement {&lt;br /&gt;&amp;nbsp; display: block;&lt;br /&gt;&amp;nbsp; +mqMinWidth(960px) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; color: red;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;The above code example says that elements with the &lt;span class="code-concept"&gt;myElement&lt;/span&gt; class always should have &lt;span class="code-concept"&gt;display: block&lt;/span&gt; in all channels. It also says that if the view port is 960 pixels or wider text inside such elements should be red.&lt;/p&gt;
&lt;p&gt;When the CSS is built (from Stylus) we create four different versions of it; one for each channel (computers, tablets, phones) and one responsive version. In the &lt;strong&gt;responsive version&lt;/strong&gt; the result of the above Stylus code is:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;.my-element {&lt;br /&gt;&amp;nbsp; display:block&lt;br /&gt;}&lt;br /&gt;@media (min-width:960px) {&lt;br /&gt;&amp;nbsp; .my-element { color:red }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;In the CSS built for &lt;strong&gt;mobile phones&lt;/strong&gt; the result is instead:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;.my-element {&lt;br /&gt;&amp;nbsp; display:block&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;In the CSS for &lt;strong&gt;tablets&lt;/strong&gt;, where the view port may or may not be wider that 960 pixels, the result is the same as in the responsive version:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;.my-element {&lt;br /&gt;&amp;nbsp; display:block&lt;br /&gt;}&lt;br /&gt;@media (min-width:960px) {&lt;br /&gt;&amp;nbsp; .my-element { color:red }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;For &lt;strong&gt;computers&lt;/strong&gt; we have a minimum width for the site that is above 960 pixels. Therefore the CSS for computers looks like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;.myElement {&lt;br /&gt;&amp;nbsp; display:block;&lt;br /&gt;&amp;nbsp; color:red&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;To summarize; after building our Stylus code we get four different CSS files. One of these makes the site responsive while the other three are heavily optimized for a specific type of device. The decision of what CSS file should be used is handled by our HTML filtering functionality. In practice the markup that includes CSS files looks like the below example prior to HTML filtering.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;link class="hidden-tablet hidden-desktop hidden-responsive" &lt;br /&gt;&amp;nbsp; href="/styles/main.mobile.css"&amp;gt;&lt;br /&gt;&amp;lt;link class="hidden-mobile hidden-desktop hidden-responsive" &lt;br /&gt;&amp;nbsp; href="/styles/main.tablet.css"&amp;gt;&lt;br /&gt;&amp;lt;link class="hidden-mobile hidden-tablet hidden-responsive" &lt;br /&gt;&amp;nbsp; href="/styles/main.desktop.css"&amp;gt;&lt;br /&gt;&amp;lt;link class="visible-responsive" &lt;br /&gt;&amp;nbsp; href="/styles/main.responsive.css"&amp;gt;&lt;/pre&gt;
&lt;p&gt;After HTML filtering, in this case for tablets, the above markup is reduced to:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;link href="/styles/main.tablet.css"&amp;gt;&amp;nbsp;&lt;/pre&gt;
&lt;h3&gt;JavaScript filtering&lt;/h3&gt;
&lt;p&gt;Last but not least we need to build channel optimized JavaScript files. The principle is the same as for CSS. We build four different JavaScript bundles, one for the responsive mode and one for each channel. Then we let the HTML filtering decide which one should be used.&lt;/p&gt;
&lt;p&gt;Unlike the CSS it's pretty rare that we do anything channel specific in our JavaScript code. In those rare cases though we can do so by inspecting the value of a number of global variables which tell us what channel the script is executing in.&lt;/p&gt;
&lt;p&gt;One example of channel filtering in JavaScript is the call to the function that displays a button for opening Expressen's iOS or Android app. This button should only be visible on devices where it's possible to run the app, i.e. tablets and phones. This is how the code for handling the call to the function looks in the responsive bundle:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;if (!CHANNEL_DESKTOP) { &lt;br /&gt;&amp;nbsp; openInApp();&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;In the responsive scenario our JavaScript bundle contains functionality that populates among others CHANNEL_DESKTOP based on the user's current view port. In the event that the user resizes the browser window the variable's value is changed and events that other code can listen to are triggered.&lt;/p&gt;
&lt;p&gt;For a specific channel the JavaScript code is processed, with the help of &lt;a href="https://www.npmjs.com/package/babel-plugin-vanilla-shake"&gt;Vanilla shake&lt;/a&gt;, and if-statements that check which channel the user is in are removed. The code inside such if-statements is either removed or left in place depending on the condition in the if-statement and what channel bundle is being built.&lt;/p&gt;
&lt;h2&gt;The result&lt;/h2&gt;
&lt;p&gt;When we first started discussing the idea of creating a responsive site that was performance optimized when facing public visitors many of us in the team were skeptical. Would this really work in practice? However, the potential benefits if it did work were very attractive so we decided to give it a try.&lt;/p&gt;
&lt;p&gt;Initially there was some effort required to create the components and functionality that I've briefly described in this post. After that initial investment each individual component and the solution in its entirety has worked well.&lt;/p&gt;
&lt;p&gt;It has also brought the benefits that we initially hoped for in terms of ways of working and thinking, although we've sometimes caught ourselves thinking in channel specific ways. That may be due to us coming from having worked with channel specific versions previously though.&lt;/p&gt;
&lt;p&gt;In terms of performance the solution has been a hit. Visitors to expressen.se only receive the HTML, CSS and JavaScript that is actually needed for the type of device that they are using. Below is an example of a Lighthouse audit of the responsive version of the site, without channel filtering:&lt;/p&gt;
&lt;p&gt;&lt;img class="thumbnail-centered" src="/PageFiles/718/lighthouse_responsivt-1.png" alt="" width="729" height="927" /&gt;&lt;/p&gt;
&lt;p&gt;Given that the start page of Expressen that is measured here is very long and contains a lot of content the above result isn't exactly bad. However, let's take a look at the result of the same audit performed against the same page but with channel filtering active. Especially note the difference in KB under the "Unused CSS rules" metric.&lt;/p&gt;
&lt;p&gt;&lt;img src="/PageFiles/718/lighthouse_kanalfiltrerat-1.png" alt="" width="729" height="835" /&gt;&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/responsibly-responsive-web-design-at-expressen/</link>
      <guid>http://joelabrahamsson.com/responsibly-responsive-web-design-at-expressen/</guid>
      <pubDate>Thu, 05 Jul 2018 17:19:42 +0100</pubDate>
      <category>Programming</category>
      <category>css</category>
      <category>javascript</category>
      <category>performance</category>
      <category>user experience</category>
    </item>
    <item>
      <title>Book announcement: ElasticSearch Quick Start</title>
      <description>I'm happy to announce a book that I've been meaning to write for quite some time - An introduction to ElasticSearch for developers in tutorial form.
&lt;p&gt;&lt;img class="thumbnail-centered" src="/PageFiles/714/es_book_screenshot.jpg" alt="" width="500" height="257" /&gt;&lt;/p&gt;
&lt;p&gt;About 18 months ago I was working on a customer project in which ElasticSearch was a major component. While I had quite a lot of prior experience with ElasticSearch something at this time got me thinking about the lack of good, simple, tutorials for helping developers new to ElasticSearch get started. So, one night I sat down and I wrote such a tutorial, a &lt;a href="/link/dfe15cc97abd451794293a4ed2017a5c.aspx?id=553&amp;amp;epslanguage=en"&gt;blog post titled "ElasticSearch 101"&lt;/a&gt;. Since it was first published it has accounted for 50-70% of the total traffic to my site and it has received a lot of positive feedback in the comments.&lt;/p&gt;
&lt;p&gt;While the positive reception of ElasticSearch 101 is great I've always felt that there's more I'd like to say on the topic. While there has been a number of extensive books about ElasticSearch published the last couple of years and I've written more blog posts about it myself I've always wanted to write a longer version of ElasticSearch 101 in the form of a book. A book that would be shorter than the typical technical book but more detailed and covering more topics than the original blog post.&lt;/p&gt;
&lt;p&gt;For 18 months I made excuses for myself for not writing this book. However, over this Christmas holiday I finally started writing. Wise from my previous book (about EPiServer CMS) I decided that I a) wouldn't strive to make each chapter perfect prior to writing the next and b) not to publish it before all chapters were done (in their first versions). This weekend I finished the (probably) last chapter and hit the publish button on Leanpub.&lt;/p&gt;
&lt;p&gt;The book is titled &lt;a href="https://leanpub.com/elasticsearch-quick-start"&gt;ElasticSearch Quick Start&lt;/a&gt;. It's not a hundred percent done yet, but it is pretty much finished in terms of the topics that it will cover. What remains is making it *perfect* based on reader feedback, possibly rewriting some parts and by adding more examples.&lt;/p&gt;
&lt;p&gt;If you're interested in ElasticSearch check it out. And, if you decide to buy it please give me feedback! I'd really like the book to be the ultimate way to learn how to be productive with ElasticSearch quickly and in order to do that reader feedback is essential.&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/book-announcement-elasticsearch-quick-start/</link>
      <guid>http://joelabrahamsson.com/book-announcement-elasticsearch-quick-start/</guid>
      <pubDate>Sun, 18 Jan 2015 20:33:54 +0100</pubDate>
      <category>Search Engines</category>
    </item>
    <item>
      <title>Notes from learning Go - the basics</title>
      <description>I recently decided to learn Go. As in Go the programming language, also known as golang. These are my notes from doing so. In the form of code.
&lt;h2&gt;Hello World&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;//Here's a comment&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Hello world")&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/vGwu1WKTGx"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Variables and types&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Variables are declared using "var [name] [type]"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var myVariable string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;myVariable = "I'm a string"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;myVariable += " and I was declared the long way"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myVariable)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var length int = len(myVariable)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("I'm this long:", length)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Using short variable declaration, omitting the var keyword&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;mySecondVariable := "I'm also a string but I was declared the short way"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(mySecondVariable)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;const constant = "I'm a constant with inferred type"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(constant)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var (&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var1 = "This is"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var2 = "multiple"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var3 = "variables"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(var1, var2, var3)&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/7--98MD-bk"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;If statements and loops&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;i := 1&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for i &amp;lt;= 5 {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(i)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;i += 1&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for i := 6; i &amp;lt;= 10; i++ {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if i % 2 == 0 {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(i, "even")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;} else if i % 3 == 0 {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(i, "divisible by 3")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(i, "odd and not divisible by 3")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/WmwIa-IY1H"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Switch&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;i := 3&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;switch i {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;case 1: fmt.Println("One")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;case 2: fmt.Println("Two")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;case 3: fmt.Println("Three")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;default: fmt.Println("Uhmn, not sure")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;switch i%2 {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;case 0: fmt.Println("Even")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;default: fmt.Println("Odd")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/Bd6WvjRrCp"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Arrays&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var myArray [5]string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;myArray[2] = "I'm the third item"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myArray)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;myArray[0] = "Woho, I'm the first item!"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myArray)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Array length:", len(myArray))&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var intArray [3]int&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("\"Empty\" int array:", intArray)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;intArray = [3]int{1, 2}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Integer array with the two first values set:", intArray)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var messageParts = [3]string{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;"Hello ",&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;"there",&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;"!",&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var message string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for i := 0; i &amp;lt; len(messageParts); i++ {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;message += messageParts[i]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(message)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Usign the range keyword. The underscore tells the compiler that we don't need the value (index in this case)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var secondMessage string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for _, value := range messageParts {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;secondMessage += value&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(secondMessage)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for idx, _ := range messageParts {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Index:", idx)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/EWBGq9bkgF"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Slices&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var myEmptySlice []string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myEmptySlice)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;sliceAssociatedWithArray := make([]int, 5)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(sliceAssociatedWithArray)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;array := [5]int{1, 2, 3, 4, 5}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;middleSlice := array[1:4]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(middleSlice)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;array[2] = 42&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(middleSlice)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;middleSlice[0] = 41&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(array)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;messageSlice := []string{"hello", "there"}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;messageSlice = append(messageSlice, "how", "are", "you")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(messageSlice)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;helloOnlySlice := make([]string, 2)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;copy(helloOnlySlice, messageSlice)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(helloOnlySlice)&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/vsGj3Yo7UA"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Maps&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var myMap map[string]string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;myMap = make(map[string]string) &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;myMap["hello"] = "hej"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myMap)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(len(myMap))&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myMap["hello"])&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;delete(myMap, "hello")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myMap)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(len(myMap))&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(myMap["hello"])&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Maps, no matter if they have been initialized or not, return the &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// zero value for the type if they key doesn't have a value&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var ints map[string]int&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(ints["nothing"]) // Outputs 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Accessing an element can return two values where the second is&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// the result of the lookup&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;value, exists := ints["nothing"]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(value) // Still 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(exists) // false&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Short way of creating maps&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;lengths := map[string]int {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;"hello": 5,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;"there": 5,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;"!": 1,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(lengths)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Iterating over elements&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for key, value := range lengths {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(key)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(value)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/pZzaCu015V"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Functions&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;secondFunction()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;thirdFunction("Hello yourself!")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fourthFunction("How", "are", "you", "today?")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(fifthFunction())&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(sixthFunction())&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;part1, part2 := seventhFunction()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(part1, part2)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(eightFunction()())&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func secondFunction() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Hello world!")&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func thirdFunction(message string) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(message)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func fourthFunction(messages ...string) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for index, message := range messages {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Print(message)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if index &amp;lt; len(messages)-1 {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Print(" ")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func fifthFunction() string {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return "Hello world as return value"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func sixthFunction() (message string) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;message = "Hello world as named return value"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return message&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func seventhFunction() (string, string) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return "Hello world", "from multiple return values"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func eightFunction() func() string {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;message := "Hello world from closure"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return func() string {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return message;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/8n1AVysx6e"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Pointers&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;message := "I'm the original, and best"&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;modifier1(message)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(message) // "I'm the original, and best"&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// The &amp;amp; operator finds the address for a variable, meaning that &amp;amp;message returns a *string&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;modifier2(&amp;amp;message)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(message) // "modifier2 was here"&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;secondMessage := new(string) // the new operatore can be used to create pointers&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;modifier2(secondMessage)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(*secondMessage) // "modifier2 was here"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func modifier1(message string) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;message = "modifier1 was here"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func modifier2(message *string) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;*message = "modifier2 was here"&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/Guy89RsvRP"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Structs&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;rect := Rectangle{width: 10, height: 5}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Height:", rect.height, "Width:", rect.width)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Area:", area(rect))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;type Rectangle struct {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;width, height int&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func area(rect Rectangle) int {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return rect.width*rect.height&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/nGqXzKRH7P"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Methods&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;rect := Rectangle{width: 10, height: 5}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Area:", rect.area())&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;type Rectangle struct {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;width, height int&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func (rect Rectangle) area() int {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return rect.width*rect.height&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/1A7mhJZXP8"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Embedding&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;bird := Bird{}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;bird.Animal.Eat()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;bird.Eat()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;bird.Fly()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;type Animal struct {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func (animal *Animal) Eat() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("I'm eating")&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;type Bird struct {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Animal&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func (bird *Bird) Fly() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("I'm flying")&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/A802eqmbgP"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Defer&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;defer first()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;second()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func first() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("First function here")&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func second() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println("Second function here")&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/c8gDJ6LYDz"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Panic and Recover&lt;/h2&gt;
&lt;pre class="prettyprint"&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;defer func() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;message := recover()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fmt.Println(message)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}()&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;panic("Something is seriously wrong")&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://play.golang.org/p/5LDtjnI4a7"&gt;Try it.&lt;/a&gt;&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/notes-from-learning-go-the-basics/</link>
      <guid>http://joelabrahamsson.com/notes-from-learning-go-the-basics/</guid>
      <pubDate>Sat, 08 Nov 2014 19:17:06 +0100</pubDate>
      <category>Programming</category>
    </item>
    <item>
      <title>Dynamic mappings and dates in ElasticSearch</title>
      <description>JSON doesn't have a date type. Yet ElasticSearch can automatically map date fields for us. While this "just works" most of the time, it can be a good idea to help ElasticSearch help us by instead using naming conventions for dates. Here's why, and how.
&lt;p&gt;ElasticSearch has a feature called dynamic mapping which is turned on by default. Using this we don't have to explicitly tell ElasticSearch how to index and store specific fields. Instead ElasticSearch figures it out itself by inspecting the content of our JSON properties.&lt;/p&gt;
&lt;p&gt;Let's look at an example.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/myindex/tweet/" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "content": "Hello World!",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": "2009-11-15T14:12:12"&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;Given that there isn't already an indexed named "myindex" the above request will cause a number of things to happen in our ElasticSearch cluster.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An index named "myindex" will be created.&lt;/li&gt;
&lt;li&gt;Mappings for a type named &lt;em&gt;tweet&lt;/em&gt; will be created for the index. The mappings will contain two properties, &lt;em&gt;content&lt;/em&gt; and &lt;em&gt;postDate&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The JSON object in the request body will be indexed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After having made the above request we can inspect the mappings that will have been automatically created with the below request.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XGET "http://localhost:9200/myindex/_mapping"&lt;/pre&gt;
&lt;p&gt;The response looks like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "myindex": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "tweet": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "properties": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "content": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "string"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "date",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "format": "dateOptionalTime"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;As we can see in the above response, ElasticSearch has mapped the &lt;em&gt;content&lt;/em&gt; property as a &lt;span class="code-concept"&gt;string&lt;/span&gt; and the &lt;em&gt;postDate&lt;/em&gt; property as a &lt;span class="code-concept"&gt;date&lt;/span&gt;.&amp;nbsp; All is well.&lt;/p&gt;
&lt;p&gt;However, let's look at what happens if we delete the index and modify our indexing request to instead look like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/myindex/tweet/" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "content": "1985-12-24",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": "2009-11-15T14:12:12"&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;In the above request the &lt;em&gt;content&lt;/em&gt; property is still a string, but the only content of the string is a date. Retrieving the mappings now gives us a different result.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "myindex": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "tweet": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "properties": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "content": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "date",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "format": "dateOptionalTime"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "date",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "format": "dateOptionalTime"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;ElasticSearch has now inferred that the &lt;em&gt;content&lt;/em&gt; property also is a &lt;span class="code-concept"&gt;date&lt;/span&gt;. If we now try to index our original JSON object we'll get an exception in our faces.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "error": "MapperParsingException[failed to parse [content]]; nested: MapperParsingException[failed to parse date field [Hello World!], tried both date format [dateOptionalTime], and timestamp number with locale []]; nested: IllegalArgumentException[Invalid format: \"Hello World!\"]; ",&lt;br /&gt;&amp;nbsp;&amp;nbsp; "status": 400&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;We're trying to insert a string value into a field which is mapped as a date. Naturally ElasticSearch won't allow us to do that.&lt;/p&gt;
&lt;p&gt;While this scenario isn't very likely to happen, when it does it can be quite annoying and cause problems that can only be fixed by re-indexing everything into a new index. Luckily there's a number of possible solutions.&lt;/p&gt;
&lt;h2&gt;Disabling date detection&lt;/h2&gt;
&lt;p&gt;As a first step we can disable date detection for dynamic mapping. Here's how we would do that explicitly for documents of type &lt;em&gt;tweet&lt;/em&gt; when creating the index:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPUT "http://localhost:9200/myindex" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "tweet": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "date_detection": false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;We then index our "problematic" tweet again:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/myindex/tweet/" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "content": "1985-12-24",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": "2009-11-15T14:12:12"&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;When we now inspect the mappings that has been dynamically created for us we see a different result compared to before:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "myindex": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "tweet": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "date_detection": false,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "properties": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "content": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "string"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "string"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Now both fields have been mapped as strings, which they indeed are, even though they contain values that can be parsed as dates. However, this isn't good either as we'd like the &lt;em&gt;postDate&lt;/em&gt; field to be mapped as a date though so that we can use range filters and the like on it.&lt;/p&gt;
&lt;h2&gt;Explicitly mapping date fields&lt;/h2&gt;
&lt;p&gt;We can explicitly map the postDate field as a date by re-creating the index and include a property mapping, like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPUT "http://localhost:9200/myindex" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "tweet": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "date_detection": false,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "properties": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "postDate": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "date"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;If we now index our "problematic" tweet with a date in the content field we'll get the desired mappings; the &lt;em&gt;content&lt;/em&gt; field mapped as a &lt;span class="code-concept"&gt;string&lt;/span&gt; and the &lt;em&gt;postDate&lt;/em&gt; field mapped as a &lt;span class="code-concept"&gt;date&lt;/span&gt;. That's nice. However, this approach can be cumbersome when dealing with many types or types that we don't know about prior to documents of those types are indexed.&lt;/p&gt;
&lt;h2&gt;Mapping date fields using naming conventions&lt;/h2&gt;
&lt;p&gt;An alternative approach to disabling date detection and explicitly mapping specific fields as dates is instruct ElasticSearchs dynamic mapping functionality to adhere to naming conventions for dates. Take a look at the below request that (again) creates an index.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPUT "http://localhost:9200/myindex" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "_default_": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "date_detection": false,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "dynamic_templates": [&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "dates": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match": ".*Date|date",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_pattern": "regex",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "mapping": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "date"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;Compared to our previous requests used to creating an index with mappings this is quite different. First of all we no longer provide mappings for the &lt;em&gt;tweet&lt;/em&gt; type. Instead we provide mappings for a type named &lt;span class="code-concept"&gt;_default_&lt;/span&gt;. This is a special type whose mappings will be used as the default "template" for all other types.&lt;/p&gt;
&lt;p&gt;As before we start by disabling date detection in the mappings. However, after that we no longer provide mappings for properties but instead provide a dynamic template named &lt;em&gt;dates&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Within the dates template we provide a pattern and specify that the pattern should be interpreted as a regular expression. Using this the template will be applied to all fields whose names either end with "Date" or whose names are exactly "date". For such fields the template instructs the dynamic mapping functionality to map them as dates.&lt;/p&gt;
&lt;p&gt;Using this approach all string fields, no matter if their values can be parsed as dates or not will be mapped as string unless the field name is something like "postDate", "updateDate" or simply "date". Fields with such names will be mapped as dates instead.&lt;/p&gt;
&lt;p&gt;While this is nice, there's one caveat. Indexing a JSON object with a property matching the naming convention for date fields but whose value can't be parsed as a date will cause an exception. Still, adhering to naming conventions for dates may be a small price to pay compared to the headaches of seemingly randomly having string fields mapped as dates simply because the first document to be indexed of a specific type happened to contain a string value that could be parsed as a date.&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/dynamic-mappings-and-dates-in-elasticsearch/</link>
      <guid>http://joelabrahamsson.com/dynamic-mappings-and-dates-in-elasticsearch/</guid>
      <pubDate>Sat, 07 Jun 2014 10:58:18 +0100</pubDate>
      <category>Search Engines</category>
      <category>elasticsearch</category>
      <category>mapping</category>
    </item>
    <item>
      <title>ElasticSearch - nested mappings and filters</title>
      <description>There's one situation where we need to help ElasticSearch to understand the structure of our data in order to be able to query it fully - when dealing with arrays of complex objects.
&lt;p&gt;Arguably one of the best features of ElasticSearch is that it allows us to index and search amongst complex JSON objects. We're not limited to a flat list of fields but can work with object graphs, like we're used to when programming with object oriented languages.&lt;/p&gt;
&lt;p&gt;However, there's one situation where we need to help ElasticSearch to understand the structure of our data in order to be able to query it fully - when dealing with arrays of complex objects.&lt;/p&gt;
&lt;p&gt;As an example, look at the below indexing request where we index a movie, including a list of the cast in the form of complex objects consisting of actors first and last names:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-1/movie/" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "title": "The Matrix",&lt;br /&gt;&amp;nbsp;&amp;nbsp; "cast": [&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "firstName": "Keanu",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "lastName": "Reeves"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "firstName": "Laurence",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "lastName": "Fishburne"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; ]&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;Given many such movies in our index we can find all movies with an actor named "Keanu" using a search request such as:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-1/movie/_search" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filtered": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_all": {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast.firstName": "keanu"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;Running the above query indeed returns The Matrix. The same is true if we try to find movies that have an actor with the first name "Keanu" and last name "Reeves":&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-1/movie/_search" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filtered": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_all": {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "bool": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "must": [&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast.firstName": "keanu"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast.lastName": "reeves"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;Or at least so it seems. However, let's see what happens if we search for movies with an actor with "Keanu" as first name and "Fishburne" as last name.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-1/movie/_search" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filtered": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_all": {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "bool": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "must": [&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast.firstName": "keanu"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast.lastName": "fishburne"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;Clearly this should, at first glance, not match The Matrix as there's no such actor amongst its cast. However, ElasticSearch will return The Matrix for the above query. After all, the movie does contain an author with "Keanu" as first name and (albeit a different) actor with "Fishburne" as last name. Based on the above query it has no way of knowing that we want the two term filters to match the same unique object in the list of actors. And even if it did, the way the data is indexed it wouldn't be able to handle that requirement.&lt;/p&gt;
&lt;h2&gt;Nested mapping and filter to the rescue&lt;/h2&gt;
&lt;p&gt;Luckily ElasticSearch provides a way for us to be able to filter on multiple fields within the same objects in arrays; mapping such fields as nested. To try this out, let's create ourselves a new index with the "actors" field mapped as nested.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPUT "http://localhost:9200/index-2" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "movie": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "properties": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "nested"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;After indexing the same movie document into the new index we can now find movies based on multiple properties of each actor by using a nested filter. Here's how we would search for movies starring an actor named "Keanu Fishburne":&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-2/movie/_search" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filtered": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_all": {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "nested": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "path": "cast",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "bool": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "must": [&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "firstName": "keanu"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "lastName": "fishburne"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;As you can see we've wrapped our initial bool filter in a nested filter. The nested filter contains a &lt;span class="code-concept"&gt;path&lt;/span&gt; property where we specify that the filter applies to the cast property of the searched document. It also contains a filter (or a query) which will be applied to each value within the nested property.&lt;/p&gt;
&lt;p&gt;As intended, running the abobe query doesn't return The Matrix while modifying it to instead match "Reeves" as last name will make it match The Matrix. However, there's one caveat.&lt;/p&gt;
&lt;h2&gt;Including nested values in parent documents&lt;/h2&gt;
&lt;p&gt;If we go back to our very first query, filtering only on actors first names without using a nested filter, like the request below, we won't get any hits.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-2/movie/_search" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filtered": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_all": {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast.firstName": "keanu"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;This happens because movie documents no longer have cast.firstName fields. Instead each element in the cast array is, internally in ElasticSearch, indexed as a separate document.&lt;/p&gt;
&lt;p&gt;Obviously we can still search for movies based only on first names amongst the cast, by using nested filters though. Like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPOST "http://localhost:9200/index-2/movie/_search" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filtered": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "query": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "match_all": {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "nested": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "path": "cast",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "filter": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "term": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "firstName": "keanu"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;The above request returns The Matrix. However, sometimes having to use nested filters or queries when all we want to do is filter on a single property is a bit tedious. To be able to utilize the power of nested filters for complex criterias while still being able to filter on values in arrays the same way as if we hadn't mapped such properties as nested we can modify our mappings so that the nested values will also be included in the parent document. This is done using the &lt;span class="code-concept"&gt;include_in_parent&lt;/span&gt; property, like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;curl -XPUT "http://localhost:9200/index-3" -d'&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; "mappings": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "movie": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "properties": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "cast": {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "nested",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "include_in_parent": true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}'&lt;/pre&gt;
&lt;p&gt;In an index such as the one created with the above request we'll both be able to filter on combinations of values within the same complex objects in the actors array using nested filters while still being able to filter on single fields without using nested filters. However, we now need to carefully consider where to use, and where to not use, nested filters in our queries as a query for "Keanu Fishburne" will match The Matrix using a regular bool filter while it won't when wrapping it in a nested filter. In other words, when using include_in_parent we may get unexpected results due to queries matching documents that it shouldn't if we forget to use nested filters.&lt;/p&gt;
</description>
      <link>http://joelabrahamsson.com/elasticsearch-nested-mapping-and-filter/</link>
      <guid>http://joelabrahamsson.com/elasticsearch-nested-mapping-and-filter/</guid>
      <pubDate>Fri, 06 Jun 2014 15:59:19 +0100</pubDate>
      <category>Search Engines</category>
      <category>elasticsearch</category>
      <category>mapping</category>
    </item>
  </channel>
</rss>