<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Eleastic Search &#8211; Best DevOps</title>
	<atom:link href="https://www.bestdevops.com/category/eleastic-search/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.bestdevops.com</link>
	<description>Lets Learn, Do it &#38; Share! Thats a Best DevOps!!!</description>
	<lastBuildDate>Tue, 13 Oct 2026 14:53:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>
	<item>
		<title>How can we become Elastic Certified Engineers?</title>
		<link>https://www.bestdevops.com/how-can-we-become-elastic-certified-engineers/</link>
		
		<dc:creator><![CDATA[rahulkr]]></dc:creator>
		<pubDate>Wed, 25 Aug 2021 14:15:57 +0000</pubDate>
				<category><![CDATA[Data Science]]></category>
		<category><![CDATA[Eleastic Search]]></category>
		<category><![CDATA[IT Monitoring]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Benefits]]></category>
		<category><![CDATA[Big data]]></category>
		<category><![CDATA[Certification]]></category>
		<category><![CDATA[Courses]]></category>
		<category><![CDATA[Elastic]]></category>
		<category><![CDATA[Elasticsearch]]></category>
		<category><![CDATA[Engineers]]></category>
		<category><![CDATA[Training and Certification]]></category>
		<guid isPermaLink="false">https://www.bestdevops.com/?p=19752</guid>

					<description><![CDATA[What is an elastic engineer? Before defining elastic search. I give you a brief explanation that you are in the [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading"><strong>What is an elastic engineer?</strong></h1>



<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img fetchpriority="high" decoding="async" src="https://www.bestdevops.com/wp-content/uploads/2021/08/elasticsearchengineer.jpg" alt="" class="wp-image-19753" width="798" height="495" srcset="https://www.bestdevops.com/wp-content/uploads/2021/08/elasticsearchengineer.jpg 960w, https://www.bestdevops.com/wp-content/uploads/2021/08/elasticsearchengineer-300x186.jpg 300w, https://www.bestdevops.com/wp-content/uploads/2021/08/elasticsearchengineer-768x477.jpg 768w" sizes="(max-width: 798px) 100vw, 798px" /></figure></div>



<p class="wp-block-paragraph">Before defining elastic search. I give you a brief explanation that you are in the field of data science and big data and you may have heard about elastic search and you might be wondering that how does search engine <a href="https://www.devopsschool.com/">technology</a> helps you in extracting meaning from your data at scale. How do you get answers in milliseconds? Let’s talk about that it started off as a scalable lucence version.it adds a horizontally scalable search engine. There are shards and each “shard” is an inverted index of documents but not just for full-text search.it only can handle structure data, &amp; can aggregate data quickly and often doing a faster solution than Hadoop/ spark /flink/etc.</p>



<p class="wp-block-paragraph">Often, you listen to engineers. Their sorts of priorities and various forms include in it. Now, among all engineering streams. Elastic is an integral part of the elastic search engineer. Let’s talk about an elastic certified engineer. An elastic engineer possesses the ability and skills on performing a necessary task to build complete solutions of elastic search and monitoring the functions of install, configure, and manage the cluster, indexing data into the clusters, query, and analyzing the index data.</p>



<h1 class="wp-block-heading"><strong>What are the benefits of elastic engineer?</strong></h1>



<div class="wp-block-image"><figure class="alignright size-full is-resized"><img decoding="async" src="https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring-1.png" alt="" class="wp-image-19754" width="544" height="370" srcset="https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring-1.png 777w, https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring-1-300x204.png 300w, https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring-1-768x523.png 768w" sizes="(max-width: 544px) 100vw, 544px" /></figure></div>



<p class="wp-block-paragraph">&nbsp;Getting ideas about the elastic engineer. Now, it’s time to take action on benefits. What’re benefits do you getting from elastic engineering and you just can’t say words for it. After the completion of the exam and certifications then you behave as you saying. There are some of the benefits according to the ideology of elastic engineer as categorized:</p>



<ul class="wp-block-list"><li><strong>Scalability</strong></li><li><strong>Really fast</strong></li><li><strong>Multilingual</strong></li><li><strong>Document oriented</strong></li><li><strong>Auto-completion &amp; instant search</strong></li><li><strong>Scheme free</strong></li></ul>



<h1 class="wp-block-heading"><strong>Why we should learn elastic engineer?</strong></h1>



<p class="wp-block-paragraph">If you are talking about the elastic engineer then first you should assemble the conceptual knowledge about why you are learning or necessity along with the cause? Through, the learning path of elastic certification. It’s proven to be fruitful in the sectors of IT entities and organizations. Due to its Performa-based courses/training along with the professionals. That will give you the using concept with skills, task building techniques on the elastic search on the basis of two courses which are packed with elastic search engineer I and elastic search engineer II. Its certification is based on the elastic search engineer exam and after completing the procedure of all. It will create awesome technological advances, feed awareness about the industry and its impacts on the environment. One of the prominent roles of elastic certification is the job opportunity, creativity, and innovation in favor of drastic enhances.</p>



<h1 class="wp-block-heading"><strong>How our elastic engineer course/training would help?</strong></h1>



<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img decoding="async" src="https://www.bestdevops.com/wp-content/uploads/2021/08/elastic-search.jpg" alt="" class="wp-image-19755" width="711" height="395" srcset="https://www.bestdevops.com/wp-content/uploads/2021/08/elastic-search.jpg 450w, https://www.bestdevops.com/wp-content/uploads/2021/08/elastic-search-300x167.jpg 300w" sizes="(max-width: 711px) 100vw, 711px" /></figure></div>



<p class="wp-block-paragraph">After taking the course structure of elastic search engineer. It will create ideology about the elastic search and perform functionalities in the areas of sharding techniques &amp; strategies, tuning for ingest speed, monitoring the stack, backing up your data, and query theory.</p>



<p class="wp-block-paragraph"> Getting command all over the ability and data experiences will make you job achiever, exam certification and build techniques to qualify in performance considerations, high availability, always use bulk, increase refresh, disable replicas, templates/mapping, monitoring, delete snapshots, general things to avoid, general things to do, and tools for console &amp; search profiler for better technology development. These training courses will help you to understand the advances in elastic search, develop skills, better performances and produce high-paid salary job opportunities towards the IT infrastructure. In this matter, I would like to prefer this course in the industry of software development for your future goals.</p>



<h3 class="wp-block-heading">Related video:</h3>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy"  id="_ytid_89466"  width="675" height="379"  data-origwidth="675" data-origheight="379" src="https://www.youtube.com/embed/DR-zJXxtefE?enablejsapi=1&#038;autoplay=0&#038;cc_load_policy=0&#038;cc_lang_pref=&#038;iv_load_policy=1&#038;loop=0&#038;rel=1&#038;fs=1&#038;playsinline=0&#038;autohide=2&#038;theme=dark&#038;color=red&#038;controls=1&#038;disablekb=0&#038;" class="__youtube_prefs__  epyt-is-override  no-lazyload" title="YouTube player"  allow="fullscreen; accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen data-no-lazy="1" data-skipgform_ajax_framebjll=""></iframe>
</div></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How do we become an Observability Certified Professional (OCP)</title>
		<link>https://www.bestdevops.com/how-do-we-become-an-observability-certified-professional-ocp/</link>
		
		<dc:creator><![CDATA[rahulkr]]></dc:creator>
		<pubDate>Wed, 11 Aug 2021 15:30:34 +0000</pubDate>
				<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[Eleastic Search]]></category>
		<category><![CDATA[IT Monitoring]]></category>
		<category><![CDATA[IT Training]]></category>
		<category><![CDATA[Benefits]]></category>
		<category><![CDATA[Courses]]></category>
		<category><![CDATA[Observability]]></category>
		<category><![CDATA[Professionals]]></category>
		<category><![CDATA[Training]]></category>
		<category><![CDATA[Training and Certification]]></category>
		<category><![CDATA[Tutorials]]></category>
		<guid isPermaLink="false">https://www.bestdevops.com/?p=18996</guid>

					<description><![CDATA[What is an Observability? Today we’re going to be talking about observability, so let’s start with a definition. So observability [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading">What is an Observability?</h1>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="744" height="400" src="https://www.bestdevops.com/wp-content/uploads/2021/08/devops-practitioner-internal-030421-2.jpg" alt="" class="wp-image-19541" srcset="https://www.bestdevops.com/wp-content/uploads/2021/08/devops-practitioner-internal-030421-2.jpg 744w, https://www.bestdevops.com/wp-content/uploads/2021/08/devops-practitioner-internal-030421-2-300x161.jpg 300w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure></div>



<p class="wp-block-paragraph">Today we’re going to be talking about observability, so let’s start with a definition. So observability is a property of your system&#8217;s software that helps you understand what’s going on with them, monitor what they’re doing. To achieve observability, you should have visibility into system software and applications then it is classified into three tiers on the basis of performances credibility as logging, metrics, and monitoring. On the account of observability, it performs a certain action as a part of diagnostic data with the help of logging, traces the matrices, and monitoring the whole sorts of data into aggregator which collects from systems software’s, devices, and cloud server includes an operating system, after Kubernetes in which applications is running. After catching all logs data it is received by the developers and security on the process of fixing the bugs or errors for schematic performances of applications software.</p>



<h1 class="wp-block-heading">What are the benefits of an Observability?</h1>



<p class="wp-block-paragraph">Now, it’s a while to check out the benefits. There are some sorts of beneficial situations on the basis of observability:-</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" src="https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring.png" alt="" class="wp-image-18999" width="527" height="435" srcset="https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring.png 766w, https://www.bestdevops.com/wp-content/uploads/2021/08/Monitoring-300x248.png 300w" sizes="auto, (max-width: 527px) 100vw, 527px" /></figure>



<ul class="wp-block-list"><li>Monitoring</li><li>Alerting /visualization</li><li>Distributed systems tracing infrastructure</li><li>Log Aggregation/analytics</li></ul>



<h1 class="wp-block-heading"><strong>Why we should learn an Observability?</strong></h1>



<p class="wp-block-paragraph">There is an awesome possibility with great impact in the case of observability. If you have software and you don’t know about the functioning series, you get opaque then how to detect or debugging the system property? With the helping hand of observability-certified professionals? You can diagnose all the logs, matrices, and monitoring and hand them over to the developer’s team. This course will help you to the functioning system well with certifications.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" src="https://www.bestdevops.com/wp-content/uploads/2021/08/download-2.jpg" alt="" class="wp-image-19000" width="592" height="332" /></figure>



<h1 class="wp-block-heading"><strong>How our Observability course/training would help?</strong> </h1>



<p class="wp-block-paragraph">In this context, of course, training will make you expertise in the fields of observability. If you have your own system programs than this training will give you technological advances and aware about the absorbing capabilities. Through this new concept you can analyze your system software program. I wish this will more clarify your mind mapping and observing performances. After completing this course you get certification and makes you professionals.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Back Up Data in AWS Elastic Block Store (EBS)</title>
		<link>https://www.bestdevops.com/back-up-the-data-in-aws-elastic-block-store/</link>
					<comments>https://www.bestdevops.com/back-up-the-data-in-aws-elastic-block-store/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Fri, 20 Sep 2019 05:09:14 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Eleastic Search]]></category>
		<category><![CDATA[data-stored]]></category>
		<category><![CDATA[EBS]]></category>
		<category><![CDATA[Elastic]]></category>
		<category><![CDATA[Web Services]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=7885</guid>

					<description><![CDATA[AWS EBS is not automatically protected against all failure scenarios. Learn how EBS replication works, why snapshots are essential, and how to build a reliable backup strategy for your EBS volumes.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Amazon Web Services Elastic Block Store (EBS) is one of the most widely used storage options in AWS, but it is not a set-and-forget solution. A past AWS US-East-1 availability zone outage — caused by a power failure and backup generator failures — resulted in a small percentage of customers losing production data permanently. Those customers had one thing in common: they had no backup of their EBS volumes.</p>



<p class="wp-block-paragraph">Understanding what EBS protects against — and, critically, what it does not — is a fundamental responsibility for any team storing important data in AWS.</p>



<h2 class="wp-block-heading">How EBS Replication Actually Works</h2>



<p class="wp-block-paragraph">Think of an EBS volume as a highly reliable virtual hard drive hosted in the cloud. EBS protects your data by replicating it across multiple physical servers within a single availability zone (AZ). This is conceptually similar to a RAID array in an on-premises data center: it guards against individual disk failure, but it does not guard against everything.</p>



<p class="wp-block-paragraph">The critical limitation is that EBS replication is confined to a single availability zone. If an event — such as a power failure affecting multiple servers simultaneously — hits that AZ, the replication that normally protects you may not be able to prevent data loss.</p>



<p class="wp-block-paragraph">More importantly, block-level replication propagates logical corruption just as readily as it propagates valid data. Logical corruption can originate from:</p>



<ul class="wp-block-list">
<li><strong>Human error</strong> — accidentally deleting files or directories</li>
<li><strong>Software bugs</strong> — application or OS errors that corrupt data on disk</li>
<li><strong>Electrical events</strong> — voltage spikes that cause unexpected writes</li>
</ul>



<p class="wp-block-paragraph">This is exactly why RAID arrays in data centers are still backed up, and it is exactly why EBS volumes must be backed up as well. Replication is not a substitute for backup.</p>



<h2 class="wp-block-heading">EBS Volume Failure Rates</h2>



<p class="wp-block-paragraph">Amazon&#8217;s own EBS product documentation states that customers should expect an annual failure rate between 0.1% and 0.2% for EBS volumes. At that rate, an environment with 1,000 volumes should statistically expect to lose one or two volumes per year under normal operating conditions — before accounting for larger outage events.</p>



<p class="wp-block-paragraph">That failure rate is far better than an individual consumer hard drive, but it is not zero, and it scales with your volume count. AWS directly recommends using EBS snapshots to protect against volume failure. That recommendation should be treated as mandatory for any production workload.</p>



<h2 class="wp-block-heading">What Are EBS Snapshots?</h2>



<p class="wp-block-paragraph">An EBS snapshot is a point-in-time image copy of an EBS volume. It differs from the &#8220;snapshot&#8221; concept used in some enterprise storage systems:</p>



<ul class="wp-block-list">
<li>The <strong>first snapshot</strong> is a full backup — a complete image copy of the volume.</li>
<li>Each <strong>subsequent snapshot</strong> is a block-level incremental backup, storing only the blocks that changed since the previous snapshot.</li>
</ul>



<p class="wp-block-paragraph">Snapshots are stored as objects in Amazon S3, though they are not visible in the S3 console. They can be used to restore an EBS volume or to create a new volume from the snapshot image.</p>



<h2 class="wp-block-heading">Ensuring Data Consistency When Taking a Snapshot</h2>



<p class="wp-block-paragraph">Because a snapshot is an image of the volume at a moment in time, you must take care to avoid capturing a volume in the middle of active writes. An inconsistent snapshot can produce a corrupted restore. There are several approaches to handle this:</p>



<h3 class="wp-block-heading">Stop the Instance (Most Reliable)</h3>



<p class="wp-block-paragraph">Shutting down the EC2 instance before taking a snapshot guarantees no writes are in flight. This is the safest method, but it is rarely practical for production systems that must remain available.</p>



<h3 class="wp-block-heading">Freeze Writes Temporarily (Linux)</h3>



<p class="wp-block-paragraph">On Linux instances, you can use filesystem-level commands to freeze writes momentarily, take the snapshot, and then unfreeze. For example, using <code>fsfreeze</code> on a mounted filesystem:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment"># Freeze the filesystem</span>
sudo fsfreeze -f /mount/point

<span class="hljs-comment"># Trigger the EBS snapshot via AWS CLI</span>
aws ec2 create-snapshot --volume-id vol-xxxxxxxx --description <span class="hljs-string">"Consistent snapshot"</span>

<span class="hljs-comment"># Unfreeze immediately after the snapshot is initiated</span>
sudo fsfreeze -u /mount/point</code></span></pre>


<p class="wp-block-paragraph">Pre- and post-scripts attached to your snapshot automation tool can handle this sequence reliably.</p>



<h3 class="wp-block-heading">Windows VSS Integration</h3>



<p class="wp-block-paragraph">If the EC2 instance runs Windows, you can integrate with the Windows Volume Shadow Copy Service (VSS). VSS coordinates with running applications to quiesce writes and produce an application-consistent snapshot before the volume-level snapshot is taken. AWS Systems Manager supports VSS-enabled EBS snapshots for Windows instances.</p>



<h2 class="wp-block-heading">Managing Snapshot Lifecycle and Costs</h2>



<p class="wp-block-paragraph">Snapshots stored in S3 incur storage costs. Without a deletion policy, accumulated snapshots can contribute meaningfully to your AWS bill. A lifecycle policy should be defined for every automated snapshot process, specifying:</p>



<ul class="wp-block-list">
<li>How frequently snapshots are taken (hourly, daily, weekly)</li>
<li>How long each snapshot is retained before deletion</li>
<li>Whether snapshots should be copied to another region or account for additional protection</li>
</ul>



<h3 class="wp-block-heading">Amazon Data Lifecycle Manager (DLM)</h3>



<p class="wp-block-paragraph">AWS provides the <strong>Amazon Data Lifecycle Manager</strong> as a native tool for automating EBS snapshot creation and deletion. DLM uses resource tags to identify which volumes to snapshot, and policies define the full lifecycle — creation schedule, retention period, and cross-region copy rules. It requires no additional software and integrates directly with IAM for access control.</p>



<p class="wp-block-paragraph">A basic DLM policy can be created in the AWS Console under <em>EC2 &gt; Elastic Block Store &gt; Lifecycle Manager</em>, or via the AWS CLI:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">aws dlm create-lifecycle-policy \
  --description <span class="hljs-string">"Daily EBS snapshots, 7-day retention"</span> \
  --state ENABLED \
  --execution-role-arn arn:aws:iam::<span class="hljs-number">123456789012</span>:role/AWSDataLifecycleManagerDefaultRole \
  --policy-details file:<span class="hljs-comment">//policy.json</span></code></span></pre>


<h3 class="wp-block-heading">Third-Party Backup Tools</h3>



<p class="wp-block-paragraph">Both free and commercial third-party tools exist that extend beyond what DLM offers natively. Commercial options can add capabilities such as:</p>



<ul class="wp-block-list">
<li>Automated cross-region snapshot copies for disaster recovery</li>
<li>Cross-account copies to protect against account-level compromise or accidental deletion</li>
<li>Centralized reporting and compliance auditing across large volume estates</li>
</ul>



<h2 class="wp-block-heading">Cross-Region and Cross-Account Copies</h2>



<p class="wp-block-paragraph">Snapshots stored in the same account and region as the source volume are still vulnerable to region-wide events or to an attacker who has gained access to that AWS account. For workloads requiring higher resilience:</p>



<ul class="wp-block-list">
<li><strong>Copy snapshots to a second region</strong> using the <code>aws ec2 copy-snapshot</code> API call or DLM cross-region copy rules.</li>
<li><strong>Copy snapshots to a separate AWS account</strong> — ideally one with tightly restricted access — so that a compromised primary account cannot delete your recovery copies.</li>
</ul>



<h2 class="wp-block-heading">Key Takeaways</h2>



<ul class="wp-block-list">
<li>EBS replication protects against individual hardware failure within an availability zone — it is not a backup.</li>
<li>Logical corruption and availability zone-level events can affect replicated data simultaneously.</li>
<li>EBS snapshots are the primary backup mechanism for EBS volumes and should be automated for every production volume.</li>
<li>Snapshot consistency matters: quiesce writes before snapshotting, using instance stop, filesystem freeze, or VSS depending on your OS.</li>
<li>Implement a lifecycle policy to control snapshot retention and keep S3 costs predictable.</li>
<li>For critical data, copy snapshots to a separate region and a separate AWS account.</li>
</ul>



<p class="wp-block-paragraph">EBS is a robust and scalable block storage service, but like any storage system, it requires a deliberate backup strategy. The operational principle that applies on-premises applies equally in the cloud: you can outsource infrastructure, but you cannot outsource the responsibility for protecting your data.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/back-up-the-data-in-aws-elastic-block-store/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Full-text search with Node.js and ElasticSearch on Docker</title>
		<link>https://www.bestdevops.com/full-text-search-with-node-js-and-elasticsearch-on-docker/</link>
					<comments>https://www.bestdevops.com/full-text-search-with-node-js-and-elasticsearch-on-docker/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Mon, 16 Sep 2019 05:48:32 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Eleastic Search]]></category>
		<category><![CDATA[codebase]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Elasticsearch]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[server]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=7747</guid>

					<description><![CDATA[Source:-blog.logrocket Full-text search can be both scary and exciting. Some popular databases such as&#160;MySql&#160;and&#160;Postgres&#160;are an amazing solution for storing data… [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Source:-blog.logrocket<br></p>



<p class="wp-block-paragraph">Full-text search can be both scary and exciting. Some popular databases such as&nbsp;<strong>MySql</strong>&nbsp;and&nbsp;<strong>Postgres</strong>&nbsp;are an amazing solution for storing data… but when it comes to full-text search performances, there’s no competition with&nbsp;<strong>ElasticSearch</strong>.</p>



<p class="wp-block-paragraph">For those who don’t know, ElasticSearch is a search engine server built on top of <strong>Lucene</strong> with an amazing distributed-architecture support. According to db-engines.com, it is currently the most used search engine out there.</p>



<p class="wp-block-paragraph">In this post, we are going to build a simple REST application called The Quotes Database which will allow us to store and search as many quotes as we want.</p>



<p class="wp-block-paragraph">I’ve prepared a JSON file containing 5000+ quotes with their authors, we’ll be using it as our starting data for populating ElasticSearch.</p>



<h2 class="wp-block-heading">Setting up Docker</h2>



<p class="wp-block-paragraph">First of all, we don’t want to install ElasticSearch on our machine. We’ll be using Docker for orchestrating both the Node.js server and the ES instance on a container, which will allow us to deploy a production-ready application with all the dependencies that it needs.</p>



<p class="wp-block-paragraph">Let’s create a&nbsp;<code>Dockerfile</code>&nbsp;inside our project root folder:</p>



<pre class="wp-block-preformatted">FROM node:10.15.3-alpine

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install
RUN npm install -g pm2

COPY . ./

EXPOSE 3000
EXPOSE 9200

CMD npm run start</pre>



<p class="wp-block-paragraph">As you can see, we’re telling Docker that we’ll run a&nbsp;<strong>Node.js 10.15.3-alpine</strong>&nbsp;runtime. We’ll also create a new working directory under&nbsp;<code>/usr/src/app</code>, where we’ll copy both the&nbsp;<code>package.json</code>&nbsp;and the&nbsp;<code>package-lock.json</code>&nbsp;files. That way, Docker will be able to run&nbsp;<code>npm install</code>&nbsp;inside our&nbsp;<code>WORKDIR</code>, installing our needed dependencies.</p>



<p class="wp-block-paragraph">We’ll also install <strong>PM2</strong> by running <code>RUN npm install -g pm2</code>. The Node.js runtime is single-threaded, so if a process crashes, the entire app needs to be restarted… <strong>PM2</strong> checks the Node.js process status and restarts it when the app goes down for any reason.</p>



<p class="wp-block-paragraph">After installing PM2, we’ll copy our codebase inside our&nbsp;<code>WORKDIR</code>&nbsp;(<code>COPY&nbsp;.&nbsp;./</code>), and we tell Docker to expose two ports,&nbsp;<code>3000</code>, which will expose our RESTful service, and&nbsp;<code>9200</code>, which exposes the ElasticSearch service (<code>EXPOSE&nbsp;3000</code>&nbsp;and&nbsp;<code>EXPOSE&nbsp;9200</code>).</p>



<p class="wp-block-paragraph">Last but not least, we tell Docker which command will start the Node.js app with&nbsp;<code>npm run start</code>.</p>



<h2 class="wp-block-heading">Setting up docker-compose</h2>



<p class="wp-block-paragraph">Now you may be saying, ‘<em>Great, I get it! But how do I handle the ElasticSearch instance inside Docker? I can’t find it in my Dockerfile!’</em>… you’re right! That’s where&nbsp;<strong>docker-compose</strong>&nbsp;becomes useful. It allows us to orchestrate multiple Docker containers and to create a connection between them. So, let’s write down the&nbsp;<code>docker-compose.yml</code>&nbsp;file, which will be stored inside our project root directory:</p>



<pre class="wp-block-preformatted">version: '3.6'
services:
  api:
    image: node:10.15.3-alpine
    container_name: tqd-node
    build: .
    ports:
      - 3000:3000
    environment:
     - NODE_ENV=local
     - ES_HOST=elasticsearch
     - NODE_PORT=3000
     - ELASTIC_URL=http://elasticsearch:9200
    volumes:
      - .:/usr/src/app/quotes
    command: npm run start
    links:
        - elasticsearch
    depends_on:
        - elasticsearch
    networks: 
      - esnet
  elasticsearch:
    container_name: tqd-elasticsearch
    image: docker.elastic.co/elasticsearch/elasticsearch:7.0.1
    volumes:
      - esdata:/usr/share/elasticsearch/data
    environment:
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.type=single-node
    logging:
      driver: none
    ports:
      - 9300:9300
      - 9200:9200
    networks: 
      - esnet
volumes:
  esdata:
networks:
  esnet:</pre>



<p class="wp-block-paragraph">This is a bit more complex than our Dockerfile, but let’s analyze it:</p>



<ul class="wp-block-list"><li>We declare which version of&nbsp;<code>docker-compose.yml</code>&nbsp;file we’re using (<code>3.6</code>)</li><li>We declare our services:<ul><li><code>api</code>, which is our Node.js app. Just like in our Dockerfile, it requires the&nbsp;<code>node:10.15.3-alpine</code>&nbsp;image. We also assign a name to this container&nbsp;<code>tqd-node</code>, and here we call the previously created Dockerfile using the&nbsp;<code>build&nbsp;.</code>&nbsp;command.</li><li>We need to expose the&nbsp;<code>3000</code>&nbsp;port so we write these statements as follows&nbsp;<code>3000:3000</code>. It means that we’re mapping&nbsp;<strong>from</strong>&nbsp;the port&nbsp;<code>3000</code>&nbsp;(inside our container)&nbsp;<strong>to</strong>&nbsp;the port&nbsp;<code>3000</code>&nbsp;(accessible from our machine). Then we’ll set some environment variables. The value&nbsp;<code>elasticsearch</code>&nbsp;is a variable which refers to the&nbsp;<code>elasticsearch</code>&nbsp;service inside our&nbsp;<code>docker-compose.yml</code>&nbsp;file.</li><li>We also want to mount a volume&nbsp;<code>/usr/src/app/quotes</code>. That way, once we restart our container we’ll maintain our data without losing it.</li><li>Once more, we tell Docker which command we need to execute once the container starts up, then we set a link to the&nbsp;<code>elasticsearch</code>&nbsp;service. We also tell Docker to start the&nbsp;<code>api</code>&nbsp;service after the&nbsp;<code>elasticsearch</code>&nbsp;service has booted (using the&nbsp;<code>depends_on</code>&nbsp;directive).</li><li>Last but not least, we tell Docker to connect the&nbsp;<code>api</code>&nbsp;service under the&nbsp;<code>esnet</code>&nbsp;network. That’s because every container has its own network. That way, we say that&nbsp;<code>api</code>&nbsp;and&nbsp;<code>elasticsearch</code>&nbsp;services shares the same network so they will be able to call each other with the same ports.</li><li><code>elasticsearch</code>, which is (as you may have guessed) our ES service. It’s configuration is pretty similar to the&nbsp;<code>api</code>&nbsp;service. We’ll just cut off its verbose logs setting the&nbsp;<code>logging</code>&nbsp;directive to&nbsp;<code>driver:&nbsp;none</code>&nbsp;.</li></ul></li><li>We also declare our volumes, where we store the ES data.</li><li>And we declare our network,&nbsp;<code>esnet</code>.</li></ul>



<h2 class="wp-block-heading">Bootstrapping the Node.js app</h2>



<p class="wp-block-paragraph">Now we need to create our Node.js application, so let’s get started setting up our&nbsp;<code>package.json</code>&nbsp;file:</p>



<pre class="wp-block-preformatted">npm init -y</pre>



<p class="wp-block-paragraph">Now we need to install some dependencies:</p>



<pre class="wp-block-preformatted">npm i -s @elastic/elasticsearch body-parser cors dotenv express</pre>



<p class="wp-block-paragraph">Great! Our&nbsp;<code>package.json</code>&nbsp;file should look like this:</p>



<pre class="wp-block-preformatted">{
  "name": "nodejselastic",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@elastic/elasticsearch": "^7.3.0",
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "dotenv": "^8.0.0",
    "express": "^4.17.1"
  }
}</pre>



<p class="wp-block-paragraph">Let’s implement our ElasticSearch connector in Node.js. First, we need to create a new&nbsp;<code>/src/elastic.js</code>&nbsp;file:</p>



<pre class="wp-block-preformatted">const { Client } = require("@elastic/elasticsearch");
                   require("dotenv").config();

const elasticUrl = process.env.ELASTIC_URL || "http://localhost:9200";
const esclient   = new Client({ node: elasticUrl });
const index      = "quotes";
const type       = "quotes";</pre>



<p class="wp-block-paragraph">As you can see, here we set some constants that will be incredibly useful. First of all, we create a new connection to ElasticSearch using its official Node.js SDK, then we define an index (<code>"quotes"</code>) and an index type(<code>"quotes"</code> again, we’ll see later what they mean).</p>



<p class="wp-block-paragraph">Now we need to create an index on ElasticSearch. You can think of “indexes” as a SQL “database” equivalent. ElasticSearch is a NoSQL database, which means that it has no tables — it just stores JSON documents. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards. You can read more about ElasticSearch indexes here.</p>



<p class="wp-block-paragraph">Let’s now define a function that will create our index:</p>



<pre class="wp-block-preformatted">async function createIndex(index) { 
  try {
    await esclient.indices.create({ index });
    console.log(`Created index ${index}`);
  } catch (err) {
    console.error(`An error occurred while creating the index ${index}:`);
    console.error(err);
  }
}</pre>



<p class="wp-block-paragraph">Now we need another function that creates the mapping for our quotes. The mapping defines the schema and types of our document:</p>



<pre class="wp-block-preformatted">async function setQuotesMapping () {
  try {
    const schema = {
      quote: {
        type: "text" 
      },
      author: {
        type: "text"
      }
    };

    await esclient.indices.putMapping({ 
      index, 
      type,
      include_type_name: true,
      body: { 
        properties: schema 
      } 
    })

    console.log("Quotes mapping created successfully");
  } catch (err) {
    console.error("An error occurred while setting the quotes mapping:");
    console.error(err);
  }
}</pre>



<p class="wp-block-paragraph">As you can see, we’re defining the schema for our documents, and we’re inserting it inside our&nbsp;<code>index</code>.</p>



<p class="wp-block-paragraph">Now let’s consider that ElasticSearch is a huge system and can take some seconds to boot up. We can’t connect to ES until it is ready, so we need a function that checks when the ES server is ready:</p>



<pre class="wp-block-preformatted">function checkConnection() {
  return new Promise(async (resolve) =&gt; {
    console.log("Checking connection to ElasticSearch...");
    let isConnected = false;
    while (!isConnected) {
      try {
        await esclient.cluster.health({});
        console.log("Successfully connected to ElasticSearch");
        isConnected = true;
      // eslint-disable-next-line no-empty
      } catch (_) {
      }
    }
    resolve(true);
  });
}</pre>



<p class="wp-block-paragraph">As you can see, we’re returning a promise. That’s because by using&nbsp;<code>async/await</code>&nbsp;we’re able to stop the entire Node.js process until this promise resolves, and it won’t do it until it connects to ES. That way, we force our Node.js to wait for ES before booting up.</p>



<p class="wp-block-paragraph">We’re done with ElasticSearch! Now let’s export our functions:</p>



<pre class="wp-block-preformatted">module.exports = {
  esclient,
  setQuotesMapping,
  checkConnection,
  createIndex,
  index,
  type
};</pre>



<p class="wp-block-paragraph">Great! Let’s see the entire&nbsp;<code>elastic.js</code>&nbsp;file:</p>



<pre class="wp-block-preformatted">const { Client } = require("@elastic/elasticsearch");
                   require("dotenv").config();
const elasticUrl = process.env.ELASTIC_URL || "http://localhost:9200";
const esclient   = new Client({ node: elasticUrl });
const index      = "quotes";
const type       = "quotes";
/**
 * @function createIndex
 * @returns {void}
 * @description Creates an index in ElasticSearch.
 */
async function createIndex(index) {
  try {
    await esclient.indices.create({ index });
    console.log(`Created index ${index}`);
  } catch (err) {
    console.error(`An error occurred while creating the index ${index}:`);
    console.error(err);
  }
}
/**
 * @function setQuotesMapping,
 * @returns {void}
 * @description Sets the quotes mapping to the database.
 */
async function setQuotesMapping () {
  try {
    const schema = {
      quote: {
        type: "text" 
      },
      author: {
        type: "text"
      }
    };
  
    await esclient.indices.putMapping({ 
      index, 
      type,
      include_type_name: true,
      body: { 
        properties: schema 
      } 
    })
    
    console.log("Quotes mapping created successfully");
  
  } catch (err) {
    console.error("An error occurred while setting the quotes mapping:");
    console.error(err);
  }
}
/**
 * @function checkConnection
 * @returns {Promise&lt;Boolean&gt;}
 * @description Checks if the client is connected to ElasticSearch
 */
function checkConnection() {
  return new Promise(async (resolve) =&gt; {
    console.log("Checking connection to ElasticSearch...");
    let isConnected = false;
    while (!isConnected) {
      try {
        await esclient.cluster.health({});
        console.log("Successfully connected to ElasticSearch");
        isConnected = true;
      // eslint-disable-next-line no-empty
      } catch (_) {
      }
    }
    resolve(true);
  });
}
module.exports = {
  esclient,
  setQuotesMapping,
  checkConnection,
  createIndex,
  index,
  type
};</pre>



<h2 class="wp-block-heading">Populating ElasticSearch with quotes</h2>



<p class="wp-block-paragraph">Now we need to populate our ES instance with our quotes. This may sound easy, but believe me, it can be tricky.</p>



<p class="wp-block-paragraph">Let’s create a new file in&nbsp;<code>/src/data/index.js</code>:</p>



<pre class="wp-block-preformatted">const elastic = require("../elastic");
const quotes  = require("./quotes.json");

const esAction = {
  index: {
    _index: elastic.index,
    _type: elastic.type
  }
};</pre>



<p class="wp-block-paragraph">As you can see, we’re importing the&nbsp;<code>elastic</code>&nbsp;module we just created and our quotes from a JSON file stored in&nbsp;<code>/src/data/quotes.json</code>. We’re also creating an object called&nbsp;<code>esAction</code>, which will tell ES how to index a document once we insert it.</p>



<p class="wp-block-paragraph">Now we need a script to populate our database. We also need to create an array of Object with the following structure:</p>



<pre class="wp-block-preformatted">[
  {
    index: {
      _index: elastic.index,
      _type:  elastic.type
    }
  },
  {
    author: "quote author",
    quote:  "quote"
  },
  ...
]</pre>



<p class="wp-block-paragraph">As you can see, for each quote we’re gonna insert, we need to set its mapping to ElasticSearch. So that’s what we’ll do:</p>



<pre class="wp-block-preformatted">async function populateDatabase() {
  const docs = [];
  for (const quote of quotes) {
    docs.push(esAction);
    docs.push(quote);
  }
  return elastic.esclient.bulk({ body: docs });
}</pre>



<p class="wp-block-paragraph">Great! Now let’s create our main file in&nbsp;<code>/src/main.js</code>&nbsp;and see how we’ll structure everything we’ve written so far:</p>



<pre class="wp-block-preformatted">const elastic = require("./elastic");
const data    = require("./data");
                require("dotenv").config();

(async function main() {

  const isElasticReady = await elastic.checkConnection();
  if (isElasticReady) {
    const elasticIndex = await elastic.esclient.indices.exists({index: elastic.index});

    if (!elasticIndex.body) {
      await elastic.createIndex(elastic.index);
      await elastic.setQuotesMapping();
      await data.populateDatabase()
    }
  }

})();</pre>



<p class="wp-block-paragraph">Let’s analyze the code above. We create a self-executing main function which will check for the ES connection. The code execution won’t proceed until ES is connected. When ES is ready, we’ll check if the&nbsp;<code>quotes</code>&nbsp;index exists. If it doesn’t, we’ll create it, we’ll set its mapping and will populate the database. Obviously, we’ll do so only the first time we start up our server!</p>



<h2 class="wp-block-heading">Creating a RESTful API</h2>



<p class="wp-block-paragraph">Now we need to create our RESTful server. We’ll be using Express.js, which is the most popular Node.js framework out there for building servers.</p>



<p class="wp-block-paragraph">We’ll start with the&nbsp;<code>/src/server/index.js</code>&nbsp;file:</p>



<pre class="wp-block-preformatted">const express      = require("express");
const cors         = require("cors");
const bodyParser   = require("body-parser");
const routes       = require("./routes");
                     require("dotenv").config();

const app  = express();
const port = process.env.NODE_PORT || 3000;

function start() {
  return  app.use(cors())
             .use(bodyParser.urlencoded({ extended: false }))
             .use(bodyParser.json())
             .use("/quotes",routes)
             .use((_req, res) =&gt; res.status(404).json({ success: false,error: "Route not found" }))
             .listen(port, () =&gt; console.log(`Server ready on port ${port}`));
}

module.exports = {
  start
};</pre>



<p class="wp-block-paragraph">As you can see, it is just a standard Express.js server, we won’t spend much time on that.</p>



<p class="wp-block-paragraph">Let’s see our&nbsp;<code>/src/server/routes/index.js</code>&nbsp;file:</p>



<pre class="wp-block-preformatted">const express    = require("express");
const controller = require("../controllers");
const routes     = express.Router();

routes.route("/").get(controller.getQuotes);
routes.route("/new").post(controller.addQuote);

module.exports = routes;</pre>



<p class="wp-block-paragraph">We just create two endpoints:</p>



<ol class="wp-block-list"><li><code>GET&nbsp;/</code>, will return a list of quotes matching our query string parameters.</li><li><code>POST&nbsp;/new/</code>, will allow us to post a new quote storing it inside ElasticSearch.</li></ol>



<p class="wp-block-paragraph">So now let’s see our&nbsp;<code>/src/server/controllers/index.js</code>&nbsp;file:</p>



<pre class="wp-block-preformatted">const model = require("../models");

async function getQuotes(req, res) {
  const query  = req.query;
  if (!query.text) {
    res.status(422).json({
      error: true,
      data: "Missing required parameter: text"
    });
    return;
  }
  try {
    const result = await model.getQuotes(req.query);
    res.json({ success: true, data: result });
  } catch (err) {
    res.status(500).json({ success: false, error: "Unknown error."});
  }
}

async function addQuote(req, res) {
  const body = req.body;
  if (!body.quote || !body.author) {
    res.status(422).json({
      error: true,
      data: "Missing required parameter(s): 'body' or 'author'"
    });
    return;
  }
  try {
    const result = await model.insertNewQuote(body.quote, body.author);
    res.json({ 
      success: true, 
      data: {
        id:     result.body._id,
        author: body.author,
        quote:  body.quote
      } 
    });
  } catch (err) {
    res.status(500).json({ success: false, error: "Unknown error."});
  }
}
module.exports = {
  getQuotes,
  addQuote
};</pre>



<p class="wp-block-paragraph">Here we’re basically defining two functions:</p>



<ol class="wp-block-list"><li><code>getQuotes</code>, which requires at least one querystring parameter –&nbsp;<code>text</code></li><li><code>addQuote</code>, which require two parameters –&nbsp;<code>author</code>&nbsp;and&nbsp;<code>quote</code></li></ol>



<p class="wp-block-paragraph">The ElasticSearch interface is delegated to our&nbsp;<code>/src/server/models/index.js</code>. This structure helps us maintain a MVC-ish architecture.</p>



<p class="wp-block-paragraph">Let’s see our model:</p>



<pre class="wp-block-preformatted">const { esclient, index, type } = require("../../elastic");

async function getQuotes(req) {
  const query = {
    query: {
      match: {
        quote: {
          query: req.text,
          operator: "and",
          fuzziness: "auto"
        }
      }
    }
  }

  const { body: { hits } } = await esclient.search({
    from:  req.page  || 0,
    size:  req.limit || 100,
    index: index, 
    type:  type,
    body:  query
  });

  const results = hits.total.value;
  const values  = hits.hits.map((hit) =&gt; {
    return {
      id:     hit._id,
      quote:  hit._source.quote,
      author: hit._source.author,
      score:  hit._score
    }
  });

  return {
    results,
    values
  }
}</pre>



<p class="wp-block-paragraph">As you can see, we’re composing our ElasticSearch query by selecting every quote that includes a given word or phrase.</p>



<p class="wp-block-paragraph">Then, we spawn the query, setting both&nbsp;<code>page</code>&nbsp;and&nbsp;<code>limit</code>&nbsp;values we can pass them in a query string, for instance&nbsp;<code>http://localhost:3000/quotes?text=love&amp;page=1&amp;limit=100</code>. If these values are not passed via querystring, we’ll fall back to their default values.</p>



<p class="wp-block-paragraph">ElasticSearch returns an incredibly big amount of data, but we just need four things:</p>



<ol class="wp-block-list"><li>Quote ID</li><li>The quote itself</li><li>Quote author</li><li>Score</li></ol>



<p class="wp-block-paragraph">The score represents how close the quote is to our search term. Once we have these values, we return them with the total results number, which may be useful when paginating the results on the front end.</p>



<p class="wp-block-paragraph">Now we need to create the last function for our model&nbsp;<code>insertNewQuote</code>:</p>



<pre class="wp-block-preformatted">async function insertNewQuote(quote, author) {
  return esclient.index({
    index,
    type,
    body: {
      quote,
      author
    }
  })
}</pre>



<p class="wp-block-paragraph">This function is really simple, we just post the quote and the author to our index and return the query result back to the controller.</p>



<p class="wp-block-paragraph">Now the complete&nbsp;<code>/src/server/models/index.js</code>&nbsp;file should look like this:</p>



<pre class="wp-block-preformatted">const { esclient, index, type } = require("../../elastic");

async function getQuotes(req) {
  const query = {
    query: {
      match: {
        quote: {
          query: req.text,
          operator: "and",
          fuzziness: "auto"
        }
      }
    }
  }

  const { body: { hits } } = await esclient.search({
    from:  req.page  || 0,
    size:  req.limit || 100,
    index: index, 
    type:  type,
    body:  query
  });

  const results = hits.total.value;

  const values  = hits.hits.map((hit) =&gt; {
    return {
      id:     hit._id,
      quote:  hit._source.quote,
      author: hit._source.author,
      score:  hit._score
    }
  });

  return {
    results,
    values
  }
}

async function insertNewQuote(quote, author) {
  return esclient.index({
    index,
    type,
    body: {
      quote,
      author
    }
  })
}

module.exports = {
  getQuotes,
  insertNewQuote
}</pre>



<p class="wp-block-paragraph">And we’re done! We just need to setup our start script inside out&nbsp;<code>package.json</code>&nbsp;file and we’re ready to go:</p>



<pre class="wp-block-preformatted">"scripts": {
  "start": "pm2-runtime start ./src/main.js --name node_app",
  "stop": "pm2-runtime stop node_app "
}</pre>



<p class="wp-block-paragraph">We also need to update our&nbsp;<code>/src/main.js</code>&nbsp;script in order to start up our Express.js server once ElasticSearch has been connected:</p>



<pre class="wp-block-preformatted">const elastic = require("./elastic");
const server  = require("./server");
const data    = require("./data");
                require("dotenv").config();

(async function main() {
  const isElasticReady = await elastic.checkConnection();

  if (isElasticReady) {
    const elasticIndex = await elastic.esclient.indices.exists({index: elastic.index});

    if (!elasticIndex.body) {
      await elastic.createIndex(elastic.index);
      await elastic.setQuotesMapping();
      await data.populateDatabase()
    }

    server.start();
  }
})();</pre>



<h2 class="wp-block-heading">Launching the application</h2>



<p class="wp-block-paragraph">We’re now ready to start our application using&nbsp;<strong>docker-compose</strong>!</p>



<p class="wp-block-paragraph">Just run the following command:</p>



<pre class="wp-block-preformatted">docker-compose up</pre>



<p class="wp-block-paragraph">You’ll need to wait until Docker downloads both the ElasticSearch and Node.js images, then it will boot up your server and you’ll be ready to query against your REST endpoints!</p>



<p class="wp-block-paragraph">Let’s test with a couple of cURL calls:</p>



<pre class="wp-block-preformatted">curl localhost:3000/quotes?text=love&amp;limit=3

{
  "success": true,
  "data": {
    "results": 716,
    "values": [
      {
        "id": "JDE3kGwBuLHMiUvv1itT",
        "quote": "There is only one happiness in life, to love and be loved.",
        "author": "George Sand",
        "score": 6.7102118
      },
      {
        "id": "JjE3kGwBuLHMiUvv1itT",
        "quote": "Live through feeling and you will live through love. For feeling is the language of the soul, and feeling is truth.",
        "author": "Matt Zotti",
        "score": 6.2868223
      },
      {
        "id": "NTE3kGwBuLHMiUvv1iFO",
        "quote": "Genuine love should first be directed at oneself if we do not love ourselves, how can we love others?",
        "author": "Dalai Lama",
        "score": 5.236455
      }
    ]
  }
}</pre>



<p class="wp-block-paragraph">So as you can see, we decided to limit our results to&nbsp;<code>3</code>, but there are over 713 quotes!</p>



<p class="wp-block-paragraph">We can easily get the next three quotes by calling:</p>



<pre class="wp-block-preformatted">curl localhost:3000/quotes?text=love&amp;limit=3&amp;page=2

{
  "success": true,
  "data": {
    "results": 716,
    "values": [
      {
        "id": "SsyHkGwBrOFNsaVmePwE",
        "quote": "Forgiveness is choosing to love. It is the first skill of self-giving love.",
        "author": "Mohandas Gandhi",
        "score": 4.93597
      },
      {
        "id": "rDE3kGwBuLHMiUvv1idS",
        "quote": "Neither a lofty degree of intelligence nor imagination nor both together go to the making of genius. Love, love, love, that is the soul of genius.",
        "author": "Wolfgang Amadeus Mozart",
        "score": 4.7821507
      },
      {
        "id": "TjE3kGwBuLHMiUvv1h9K",
        "quote": "Speak low, if you speak love.",
        "author": "William Shakespeare",
        "score": 4.6697206
      }
    ]
  }
}</pre>



<p class="wp-block-paragraph">And what if you need to insert a new quote? Just call the&nbsp;<code>/quotes/new</code>&nbsp;endpoint!</p>



<pre class="wp-block-preformatted">curl --request POST \
     --url http://localhost:3000/quotes/new \
     --header 'content-type: application/json' \
     --data '{
        "author": "Michele Riva",
        "quote": "Using Docker and ElasticSearch is challenging, but totally worth it."
}'</pre>



<p class="wp-block-paragraph">and the response will be:</p>



<pre class="wp-block-preformatted">{
  "success": true,
  "data": {
    "id": "is2QkGwBrOFNsaVmFAi8",
    "author": "Michele Riva",
    "quote": "Using Docker and ElasticSearch is challenging, but totally worth it."
  }
}</pre>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Docker makes it incredibly easy to manage our dependencies and their deployment. From that point, we could host our application on Heroku, AWS ECS, Google Cloud Container or any other Docker-based service with ease, without struggling to setup our server with their super-complex configurations.</p>



<p class="wp-block-paragraph">Next steps?</p>



<ul class="wp-block-list"><li>Learn how to use Kubernetes in order to scale your container and orchestrate more ElasticSearch Instances!</li><li>Create a new endpoint that will allow you to update an existing quote. Mistakes can happen!</li><li>And what about deleting a quote? How would you implement that endpoint?</li><li>It would be great to save your quotes with tags (for instances, quotes about love, health, art)… try to update your <code>quotes</code> index!</li></ul>



<p class="wp-block-paragraph">Software development is fun. With Docker, Node, and ElasticSearch it’s even better!</p>



<h2 class="wp-block-heading">Plug: LogRocket, a DVR for web apps</h2>



<figure class="wp-block-image"><a href="https://logrocket.com/signup/" target="_blank" rel="noreferrer noopener"><img decoding="async" src="https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&amp;ssl=1" alt="LogRocket Dashboard Free Trial Banner" class="wp-image-46"/></a></figure>



<p class="wp-block-paragraph">LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.</p>



<p class="wp-block-paragraph">In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/full-text-search-with-node-js-and-elasticsearch-on-docker/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
