<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ search - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ search - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:24:25 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/search/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use Context Hub (chub) to Build a Companion Relevance Engine
 ]]>
                </title>
                <description>
                    <![CDATA[ Large language models can write code quickly, but they still misremember APIs, miss version-specific details, and forget what they learned at the end of a session. That is the problem Context Hub is t ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-context-hub-chub-to-build-a-companion-relevance-engine/</link>
                <guid isPermaLink="false">69e299d0fd22b8ad6276817b</guid>
                
                    <category>
                        <![CDATA[ context-hub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agentic AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agents ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Open Source ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nataraj Sundar ]]>
                </dc:creator>
                <pubDate>Fri, 17 Apr 2026 20:36:32 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/14f9768e-436d-4c7e-b86c-3d380e821354.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Large language models can write code quickly, but they still misremember APIs, miss version-specific details, and forget what they learned at the end of a session.</p>
<p>That is the problem Context Hub is trying to solve.</p>
<p>Context Hub (<code>chub</code>) gives coding agents curated, versioned documentation and skills that they can search and fetch through a CLI. It also gives them two learning loops: local annotations for agent memory and feedback for maintainers.</p>
<p>In this tutorial, you'll learn how the official <code>chub</code> workflow works, how Context Hub organizes docs and skills, how annotations and feedback create a memory loop, and how to build a <a href="https://github.com/natarajsundar/context-hub-relevance-engine/">companion relevance engine</a> that improves retrieval without breaking the upstream content model.</p>
<p>This tutorial uses two public repositories side by side:</p>
<ul>
<li><p>the official upstream project: <a href="https://github.com/andrewyng/context-hub">andrewyng/context-hub</a></p>
</li>
<li><p>the companion implementation for this article: <a href="https://github.com/natarajsundar/context-hub-relevance-engine/">natarajsundar/context-hub-relevance-engine</a></p>
</li>
</ul>
<p>I've also opened a corresponding upstream pull request from my fork to the main project. If you want to track that work from the article, use the upstream pull request list filtered by author: <a href="https://github.com/andrewyng/context-hub/pulls?q=is%3Apr+author%3Anatarajsundar">andrewyng/context-hub pull requests by <code>natarajsundar</code></a>.</p>
<h2 id="heading-what-well-build">What We'll Build</h2>
<p>By the end of this tutorial, you'll have:</p>
<ul>
<li><p>a clear mental model for how Context Hub works</p>
</li>
<li><p>a working local install of the official <code>chub</code> CLI</p>
</li>
<li><p>a repeatable workflow for search, fetch, annotations, and feedback</p>
</li>
<li><p>a companion repo that adds an additive reranking layer on top of a Context-Hub-style content tree</p>
</li>
<li><p>a small benchmark and local comparison UI you can run end to end</p>
</li>
<li><p>a clear bridge between the companion repo and the smaller upstream PR</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, make sure you have:</p>
<ul>
<li><p>Node.js 18 or newer</p>
</li>
<li><p>npm</p>
</li>
<li><p>comfort with the terminal</p>
</li>
<li><p>basic familiarity with Markdown</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a href="#heading-how-to-understand-context-hub">How to Understand Context Hub</a></p>
</li>
<li><p><a href="#heading-how-to-understand-the-official-repo-the-companion-repo-and-the-upstream-pr">How to Understand the Official Repo, the Companion Repo, and the Upstream PR</a></p>
</li>
<li><p><a href="#heading-how-to-install-and-use-the-official-cli">How to Install and Use the Official CLI</a></p>
</li>
<li><p><a href="#heading-how-to-understand-docs-skills-and-the-content-layout">How to Understand Docs, Skills, and the Content Layout</a></p>
</li>
<li><p><a href="#heading-how-to-use-incremental-fetch-and-layered-sources">How to Use Incremental Fetch and Layered Sources</a></p>
</li>
<li><p><a href="#heading-how-to-use-annotations-and-feedback-to-create-a-memory-loop">How to Use Annotations and Feedback to Create a Memory Loop</a></p>
</li>
<li><p><a href="#heading-how-to-see-where-relevance-still-misses">How to See Where Relevance Still Misses</a></p>
</li>
<li><p><a href="#heading-how-the-companion-relevance-engine-improves-retrieval">How the Companion Relevance Engine Improves Retrieval</a></p>
</li>
<li><p><a href="#heading-how-to-run-the-companion-repo-end-to-end">How to Run the Companion Repo End to End</a></p>
</li>
<li><p><a href="#heading-how-to-read-the-benchmark-honestly">How to Read the Benchmark Honestly</a></p>
</li>
<li><p><a href="#heading-how-to-connect-the-companion-repo-to-the-upstream-pr">How to Connect the Companion Repo to the Upstream PR</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a href="#heading-sources">Sources</a></p>
</li>
</ol>
<h2 id="heading-how-to-understand-context-hub">How to Understand Context Hub</h2>
<p>Context Hub is easiest to understand as a workflow for turning fast-moving documentation into a reliable input for coding agents.</p>
<p>Instead of asking an agent to rely on whatever it remembers from training data, you give it a predictable contract:</p>
<ol>
<li><p>search for the right entry</p>
</li>
<li><p>fetch the right doc or skill</p>
</li>
<li><p>write code against that curated content</p>
</li>
<li><p>save local lessons as annotations</p>
</li>
<li><p>send doc-quality feedback back to maintainers</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/09d75c85-fbb0-4c9a-86d5-8acdff4e1abf.png" alt="Diagram showing the Context Hub loop from developer prompt to agent search and fetch, then annotations and maintainer feedback." style="display:block;margin:0 auto" width="1654" height="307" loading="lazy">

<p>That system boundary matters.</p>
<p>It makes the agent easier to audit, easier to improve, and easier to extend. It also keeps the interface small enough that you can reason about where the failures happen. If the agent still misses the answer, you can ask whether the problem happened during search, fetch, context selection, or generation.</p>
<h2 id="heading-how-to-understand-the-official-repo-the-companion-repo-and-the-upstream-pr">How to Understand the Official Repo, the Companion repo, and the Upstream PR</h2>
<p>This tutorial is intentionally split across two codebases and one contribution path.</p>
<p>The official upstream project, <a href="https://github.com/andrewyng/context-hub">andrewyng/context-hub</a>, is the source of truth for the real CLI, the content model, and the documented workflows. That's the codebase you should use to learn how <code>chub</code> works today.</p>
<p>The companion repository, <a href="https://github.com/natarajsundar/context-hub-relevance-engine/">natarajsundar/context-hub-relevance-engine</a>, is where the relevant ideas in this article are made concrete. It's a companion implementation, not a replacement product. Its job is to make retrieval tradeoffs visible, measurable, and easy to run locally.</p>
<p>The upstream PR is the bridge between those two worlds. The companion repo is where you can iterate faster on benchmarks, reranking, and the comparison UI. The upstream PR is where the smallest reviewable slices can be proposed back to the main project. You can track that thread here: <a href="https://github.com/andrewyng/context-hub/pulls?q=is%3Apr+author%3Anatarajsundar">upstream PR search filtered by author</a>.</p>
<p>That three-part framing keeps the article honest:</p>
<ul>
<li><p><strong>use the upstream repo</strong> to understand the current system</p>
</li>
<li><p><strong>use the companion repo</strong> to explore relevant improvements end to end</p>
</li>
<li><p><strong>use the upstream PR</strong> to show how a larger idea can be broken into reviewable pieces</p>
</li>
</ul>
<h2 id="heading-how-to-install-and-use-the-official-cli">How to Install and Use the Official CLI</h2>
<p>The official quick start is intentionally small.</p>
<pre><code class="language-bash">npm install -g @aisuite/chub
</code></pre>
<p>Once the CLI is installed, you can search for what is available and fetch a specific entry:</p>
<pre><code class="language-bash">chub search openai
chub get openai/chat --lang py
</code></pre>
<p>That's the happy path, but it helps to think through the request flow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/c5ff71d4-5e51-48b8-bbd3-fc2aafa93b9d.png" alt="Sequence diagram showing the developer asking the agent for current docs, the agent calling chub search and chub get, and the CLI fetching docs from the registry." style="display:block;margin:0 auto" width="1416" height="683" loading="lazy">

<p>In practice, the most useful detail is that the CLI is designed for the <strong>agent</strong> to use, not just for the human to use by hand.</p>
<p>That's why the upstream CLI also ships a <code>get-api-docs</code> skill. For example, if you use Claude Code, you can copy the skill into your local project like this:</p>
<pre><code class="language-bash">mkdir -p .claude/skills
cp $(npm root -g)/@aisuite/chub/skills/get-api-docs/SKILL.md \
  .claude/skills/get-api-docs.md
</code></pre>
<p>That step teaches the agent a retrieval habit:</p>
<blockquote>
<p>Before you write code against a third-party SDK or API, use <code>chub</code> instead of guessing.</p>
</blockquote>
<p>That behavioral rule is often as important as the docs themselves.</p>
<h2 id="heading-how-to-understand-docs-skills-and-the-content-layout">How to Understand Docs, Skills, and the Content Layout</h2>
<p>Context Hub separates content into two categories:</p>
<ul>
<li><p><strong>docs</strong>, which answer “what should the agent know?”</p>
</li>
<li><p><strong>skills</strong>, which answer “how should the agent behave?”</p>
</li>
</ul>
<p>That distinction makes the content model easier to scale. Docs can be versioned and language-specific. Skills can stay short and operational.</p>
<p>The directory structure is also predictable. The content guide organizes entries by author, then by <code>docs</code> or <code>skills</code>, then by entry name.</p>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/3ac72bc2-c869-4e2e-9294-d63b35991135.png" alt="Diagram showing the content tree from author to docs and skills, with DOC.md and SKILL.md feeding a build step that emits registry and search artifacts." style="display:block;margin:0 auto" width="674" height="739" loading="lazy">

<p>A small example looks like this:</p>
<pre><code class="language-text">author/docs/payments/python/DOC.md
author/docs/payments/python/references/errors.md
author/skills/login-flows/SKILL.md
</code></pre>
<p>This is one of the reasons Context Hub is easy to work with.</p>
<p>The shape of the content is plain Markdown, the main entry file is predictable, and the build output is inspectable. You don't have to reverse engineer a hidden prompt layer to figure out what the agent is reading.</p>
<h2 id="heading-how-to-use-incremental-fetch-and-layered-sources">How to Use Incremental Fetch and Layered Sources</h2>
<p>One of the best design choices in Context Hub is that it doesn't force you to inject every file into the model on every request.</p>
<p>Instead, the entry file gives you the overview, and the reference files hold the deeper material.</p>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/88d80a48-c991-495a-af25-14a0c0ac9868.png" alt="Diagram showing how chub get can fetch just the main entry file, a specific reference file, or the full entry directory." style="display:block;margin:0 auto" width="592" height="460" loading="lazy">

<p>That lets you fetch content in progressively larger slices.</p>
<pre><code class="language-bash">chub get stripe/webhooks --lang py
chub get stripe/webhooks --lang py --file references/raw-body.md
chub get stripe/webhooks --lang py --full
</code></pre>
<p>This is a token-budget feature as much as it is a documentation feature. A good agent should first load the overview, decide what part of the task matters, and only then fetch the specific supporting file.</p>
<p>Context Hub also supports layered sources. You can merge public content with your own local build output through <code>~/.chub/config.yaml</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/67465254-7a7c-4cfc-b9f0-9e94d8c3e2f3.png" alt="Diagram showing community, official, and local team sources merging into one search surface for chub search and chub get." style="display:block;margin:0 auto" width="774" height="460" loading="lazy">

<p>A minimal configuration looks like this:</p>
<pre><code class="language-yaml">sources:
  - name: community
    url: https://cdn.aichub.org/v1
  - name: my-team
    path: /opt/team-docs/dist
</code></pre>
<p>That means you can keep public docs in one lane and team-specific runbooks in another lane while still giving the agent one search surface.</p>
<h2 id="heading-how-to-use-annotations-and-feedback-to-create-a-memory-loop">How to Use Annotations and Feedback to Create a Memory Loop</h2>
<p>Context Hub has two different improvement channels.</p>
<p>Annotations are local. They help your agent remember what worked last time. Feedback is shared. It helps maintainers improve the docs for everyone.</p>
<p>That distinction matters because not every lesson belongs in the shared registry. Some lessons are environment-specific. Others point to content quality issues that should be fixed centrally.</p>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/a8514430-08cb-4085-8047-64df25c603c7.png" alt="Diagram showing the agent fetch/write cycle, then branching to local annotations or maintainer feedback before the next task." style="display:block;margin:0 auto" width="808" height="798" loading="lazy">

<p>Here is what local memory looks like in practice:</p>
<pre><code class="language-bash">chub annotate stripe/webhooks \
  "Remember: Flask request.data must stay raw for Stripe signature verification."
</code></pre>
<p>And here's the feedback path:</p>
<pre><code class="language-bash">chub feedback stripe/webhooks up
</code></pre>
<p>That loop is simple, but it's one of the most important ideas in the project. It turns a one-off debugging lesson into either persistent local memory or a signal that the shared docs need to improve.</p>
<h2 id="heading-how-to-see-where-relevance-still-misses">How to See Where Relevance Still Misses</h2>
<p>The upstream project already has a real ranking story. It uses BM25 and lexical rescue so that package-like identifiers, exact tokens, and fuzzy matches still have a chance to surface.</p>
<p>That is a strong baseline.</p>
<p>But developer queries are often much messier than package names.</p>
<p>People search for:</p>
<ul>
<li><p><code>rrf</code></p>
</li>
<li><p><code>signin</code></p>
</li>
<li><p><code>pg vector</code></p>
</li>
<li><p><code>hnsw</code></p>
</li>
<li><p><code>raw body stripe</code></p>
</li>
</ul>
<p>Those aren't “bad” queries. They're realistic shorthand.</p>
<p>And they expose an opportunity in the content model itself: many of the exact answers live in reference files such as <code>references/rrf.md</code>, <code>references/raw-body.md</code>, and <code>references/hnsw.md</code>.</p>
<p>So the question is not whether the current search works at all. It clearly does. The better question is this:</p>
<blockquote>
<p>How can you improve retrieval without breaking the content contract that already makes Context Hub useful?</p>
</blockquote>
<p>The answer in the companion repo is to keep the current model and add a reranking layer on top of it.</p>
<h2 id="heading-how-the-companion-relevance-engine-improves-retrieval">How the Companion Relevance Engine Improves Retrieval</h2>
<p>The companion repository in this article is <a href="https://github.com/natarajsundar/context-hub-relevance-engine/"><code>context-hub-relevance-engine</code></a>.</p>
<p>It keeps the same broad ideas that make Context Hub attractive:</p>
<ul>
<li><p>plain Markdown content</p>
</li>
<li><p><code>DOC.md</code> and <code>SKILL.md</code> entry points</p>
</li>
<li><p>build artifacts you can inspect</p>
</li>
<li><p>local annotations and feedback</p>
</li>
<li><p>progressive fetch behavior</p>
</li>
</ul>
<p>Then it adds one new build artifact: <code>signals.json</code>.</p>
<p>At build time, the engine extracts extra signals such as:</p>
<ul>
<li><p>headings from the main file</p>
</li>
<li><p>titles and tokens from reference files</p>
</li>
<li><p>language and version metadata</p>
</li>
<li><p>source metadata and freshness</p>
</li>
<li><p>annotation overlap</p>
</li>
<li><p>feedback priors</p>
</li>
</ul>
<p>The first pass stays cheap and transparent. The reranker only runs after the baseline has done its work.</p>
<img src="https://cdn.hashnode.com/uploads/covers/694ca88d5ac09a5d68c63854/2ed2dadb-8fff-41ee-904b-0792cafcf744.png" alt="Diagram showing the relevance pipeline from query to BM25 and lexical rescue, then synonym expansion, candidate set building, reranking signals, and final results." style="display:block;margin:0 auto" width="1399" height="541" loading="lazy">

<p>That approach matters for two reasons.</p>
<p>First, it's additive. You don't have to redesign the content tree.</p>
<p>Second, it's measurable. You can define concrete failure modes, fix them one by one, and run the same benchmark every time you change the scorer.</p>
<h2 id="heading-how-to-run-the-companion-repo-end-to-end">How to Run the Companion Repo End to End</h2>
<p>Open the repository on <a href="https://github.com/natarajsundar/context-hub-relevance-engine/">GitHub</a>, clone it using GitHub’s normal clone flow, and then run the commands below from the project root.</p>
<pre><code class="language-bash">cd context-hub-relevance-engine
npm install
npm run build
npm test
</code></pre>
<p>The repository has no third-party runtime dependencies, so <code>npm install</code> is mostly there to keep the workflow familiar. The main commands are all plain Node scripts.</p>
<h3 id="heading-how-to-reproduce-a-baseline-miss">How to Reproduce a Baseline Miss</h3>
<p>Start with the query <code>rrf</code>.</p>
<pre><code class="language-bash">node bin/chub-lab.mjs search rrf --mode baseline --lang python
</code></pre>
<p>Expected output:</p>
<pre><code class="language-text">No results.
</code></pre>
<p>Now run the improved mode.</p>
<pre><code class="language-bash">node bin/chub-lab.mjs search rrf --mode improved --lang python
</code></pre>
<p>Expected top result:</p>
<pre><code class="language-text">langchain/retrievers [doc] score=320.24
  Composable retrieval patterns for hybrid search, parent documents, query expansion, and reranking.
</code></pre>
<p>That win happens because the improved mode looks beyond the top-level entry description. It also sees the reference file title <code>rrf</code>, the related terms from query expansion, and the broader token overlap in the extracted signals.</p>
<h3 id="heading-how-to-reproduce-a-workflow-intent-win">How to Reproduce a Workflow-intent Win</h3>
<p>Try a sign-in query.</p>
<pre><code class="language-bash">node bin/chub-lab.mjs search signin --mode baseline
node bin/chub-lab.mjs search signin --mode improved
</code></pre>
<p>The baseline misses. The improved mode returns <code>playwright-community/login-flows</code> because the reranker treats <code>signin</code>, <code>sign in</code>, <code>login</code>, and <code>authentication</code> as related intent.</p>
<h3 id="heading-how-to-test-the-memory-loop">How to Test the Memory Loop</h3>
<p>Write a local note:</p>
<pre><code class="language-bash">node bin/chub-lab.mjs annotate stripe/webhooks \
  "Remember: Flask request.data must stay raw for Stripe signature verification."
</code></pre>
<p>Then fetch the doc:</p>
<pre><code class="language-bash">node bin/chub-lab.mjs get stripe/webhooks --lang python
</code></pre>
<p>You will see the main doc content, the list of available reference files, and the appended annotation.</p>
<p>That's the behavior you want from an agent memory loop: learn once, reuse many times.</p>
<h3 id="heading-how-to-run-the-benchmark">How to Run the Benchmark</h3>
<p>Start from an empty store:</p>
<pre><code class="language-bash">npm run reset-store
node bin/chub-lab.mjs evaluate
</code></pre>
<p>The included synthetic stress set reports the following summary with an empty store:</p>
<table>
<thead>
<tr>
<th>Mode</th>
<th>Top-1 Accuracy</th>
<th>MRR</th>
</tr>
</thead>
<tbody><tr>
<td>baseline</td>
<td>0.333</td>
<td>0.333</td>
</tr>
<tr>
<td>improved</td>
<td>1.000</td>
<td>1.000</td>
</tr>
</tbody></table>
<p>You can also seed the store and rerun the evaluation:</p>
<pre><code class="language-bash">npm run seed-demo
node bin/chub-lab.mjs evaluate
</code></pre>
<p>That demonstrates how annotations and feedback can push relevant entries even higher when the query overlaps with the agent’s own history.</p>
<h3 id="heading-how-to-launch-the-local-comparison-ui">How to Launch the Local Comparison UI</h3>
<pre><code class="language-bash">npm run serve
</code></pre>
<p>Then open <code>http://localhost:8787</code> in your browser.</p>
<p>The UI lets you compare baseline and improved retrieval, inspect stored annotations and feedback, rebuild the local artifacts, and rerun the benchmark from one place.</p>
<h2 id="heading-how-to-read-the-benchmark-honestly">How to Read the Benchmark Honestly</h2>
<p>The benchmark in this repo is intentionally small.</p>
<p>That is a feature, not a flaw.</p>
<p>The point is not to claim universal search quality. The point is to make a handful of realistic failure modes easy to reproduce:</p>
<ul>
<li><p>acronym queries</p>
</li>
<li><p>shorthand workflow queries</p>
</li>
<li><p>reference-file topic queries</p>
</li>
<li><p>memory-aware reranking</p>
</li>
</ul>
<p>That keeps the evaluation honest.</p>
<p>If a future scoring change breaks <code>rrf</code>, <code>signin</code>, or <code>raw body stripe</code>, you'll know immediately. And if you add a stronger dataset later, you can keep these tests as regression guards.</p>
<p>The benchmark files included in the repo are:</p>
<ul>
<li><p><code>demo/benchmark.json</code></p>
</li>
<li><p><code>docs/benchmark-empty-store.json</code></p>
</li>
<li><p><code>docs/benchmark-seeded-store.json</code></p>
</li>
<li><p><code>docs/relevance-improvement-plan.md</code></p>
</li>
</ul>
<h2 id="heading-how-to-connect-the-companion-repo-to-the-upstream-pr">How to Connect the Companion Repo to the Upstream PR</h2>
<p>A good companion repo is broad enough to explore ideas quickly. A good upstream PR is narrow enough to review.</p>
<p>That's why the two shouldn't be identical.</p>
<p>The companion repository is where you can keep the full relevance story together:</p>
<ul>
<li><p>the local comparison UI</p>
</li>
<li><p>the synthetic benchmark</p>
</li>
<li><p>the richer reranking signals</p>
</li>
<li><p>the debug and explain surfaces</p>
</li>
<li><p>the documentation that walks through tradeoffs end to end</p>
</li>
</ul>
<p>The upstream PR should be smaller and more surgical. In practice, that usually means proposing the most reviewable slices first, such as:</p>
<ol>
<li><p>reference-file signal extraction</p>
</li>
<li><p>explainable score output for debugging</p>
</li>
<li><p>a lightweight benchmark fixture format</p>
</li>
<li><p>one additive reranking hook behind a flag</p>
</li>
</ol>
<p>That keeps the main repository maintainable while still letting the article and companion repo tell the full engineering story. The upstream thread for this work lives here: <a href="https://github.com/andrewyng/context-hub/pulls?q=is%3Apr+author%3Anatarajsundar">andrewyng/context-hub pull requests by <code>natarajsundar</code></a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>What makes Context Hub interesting is not just that it stores documentation. It gives you a clear system boundary for improving coding agents.</p>
<p>You can inspect what the agent reads. You can decide when it should retrieve. You can layer public and private sources. You can persist local lessons. And you can improve ranking without tearing the whole model apart.</p>
<p>The companion relevance engine shows how to keep what already works, make one part of the system measurably better, and package the result in a way other developers can run, inspect, and extend. The upstream PR, in turn, shows how to turn a broad idea into smaller pieces that are realistic to review in the main project.</p>
<h2 id="heading-diagram-attribution">Diagram Attribution</h2>
<p>All diagrams used in this article were created by the author specifically for this tutorial and its companion repository.</p>
<h2 id="heading-sources">Sources</h2>
<ul>
<li><p><a href="https://github.com/andrewyng/context-hub">Context Hub repository</a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/blob/main/README.md">Context Hub README</a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/blob/main/cli/README.md">Context Hub CLI README</a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/blob/main/docs/cli-reference.md">Context Hub CLI reference</a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/blob/main/docs/content-guide.md">Context Hub content guide</a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/blob/main/docs/byod-guide.md">Context Hub bring-your-own-docs guide</a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/blob/main/docs/feedback-and-annotations.md">Context Hub feedback and annotations guide</a></p>
</li>
<li><p><a href="https://github.com/natarajsundar/context-hub-relevance-engine/">Companion repository: <code>context-hub-relevance-engine</code></a></p>
</li>
<li><p><a href="https://github.com/andrewyng/context-hub/pulls?q=is%3Apr+author%3Anatarajsundar">Upstream pull request search filtered by author</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build an AI-Driven Search Experience using Meilisearch ]]>
                </title>
                <description>
                    <![CDATA[ Search is one of the most important features in modern applications. Users expect instant answers, useful suggestions, and results that match their intent even when they make spelling mistakes.  Most traditional search systems struggle to deliver thi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-ai-driven-search-experience-using-meilisearch/</link>
                <guid isPermaLink="false">692782273df4e33b78a46d72</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Wed, 26 Nov 2025 22:41:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764196860843/a3dc07e2-6a90-4d4c-8b21-0f833ff41ac2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Search is one of the most important features in modern applications. Users expect instant answers, useful suggestions, and results that match their intent even when they make spelling mistakes. </p>
<p>Most traditional search systems struggle to deliver this experience without complex and heavy infrastructure. </p>
<p><a target="_blank" href="https://github.com/meilisearch/meilisearch">Meilisearch</a> is an open-source search engine that changes this by offering a fast and developer-friendly engine that is easy to set up and extend. </p>
<p>When you combine Meilisearch with AI models for natural language understanding and <a target="_blank" href="https://www.turingtalks.ai/p/how-to-perform-sentence-similarity-check-using-sentence-transformers">semantic relevance</a>, you can build a powerful and intuitive search experience that feels modern and intelligent.</p>
<p>This article explains how Meilisearch works, how to set it up, and how to integrate AI models to deliver better relevance and better ranking. You will also see how hybrid search and semantic embeddings work, and how to deploy Melisearch to the cloud using Sevalla.</p>
<h2 id="heading-what-well-cover">What We’ll Cover</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-understanding-meilisearch">Understanding Meilisearch</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-setting-up-meilisearch">Setting Up Meilisearch</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-hybrid-search-and-ai-together">Using Hybrid Search and AI Together</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-ai-to-rewrite-queries">Using AI To Rewrite Queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-deploying-meilisearch-to-the-cloud-using-sevalla">Deploying Meilisearch to the Cloud using Sevalla</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-understanding-meilisearch">Understanding Meilisearch</h2>
<p>Meilisearch is a lightning-fast search engine that fits easily into any application. </p>
<p>It’s built in Rust and designed to deliver results in less than fifty milliseconds. It supports semantic search, hybrid search, typo tolerance, sorting, geosearch, and many different languages. </p>
<p>Melisearch also provides a clean RESTful API and a wide range of SDKs that make integration easy with JavaScript, Python, Go, PHP, Ruby, Rust, and various other languages.</p>
<p>You can try Meilisearch by exploring the <a target="_blank" href="https://saas.meilisearch.com/deals">official demos</a>. These demos show how Meilisearch is not limited to one specific use case but can fit many types of workflows.</p>
<p>Meilisearch supports two editions. The Community Edition is fully open source under the MIT license and can be used freely even for commercial products. </p>
<p>The Enterprise Edition introduces features like <a target="_blank" href="https://aws.amazon.com/what-is/database-sharding/">sharding</a> and is governed by a commercial license. You can deploy Meilisearch yourself or choose Meilisearch Cloud, which handles hosting, updates, monitoring and analytics without requiring server maintenance.</p>
<h2 id="heading-setting-up-meilisearch">Setting Up Meilisearch</h2>
<p>Starting Meilisearch is simple. You can download the binary and run it directly or you can start it through Docker. Running through Docker is the fastest way to test it on your machine.</p>
<pre><code class="lang-python">docker run -it --rm -p <span class="hljs-number">7700</span>:<span class="hljs-number">7700</span> getmeili/meilisearch:latest
</code></pre>
<p>Once the server is running, you can communicate with it using HTTP. The simplest use case is indexing documents into an index and querying them. Here is an example using Python:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests

docs = [
    {<span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"title"</span>: <span class="hljs-string">"AI in Finance"</span>, <span class="hljs-string">"text"</span>: <span class="hljs-string">"How AI is changing banks"</span>},
    {<span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"title"</span>: <span class="hljs-string">"AI in Law"</span>, <span class="hljs-string">"text"</span>: <span class="hljs-string">"How AI helps legal teams"</span>},
]
requests.put(
    <span class="hljs-string">"http://localhost:7700/indexes/articles/documents"</span>,
    json=docs
)
</code></pre>
<p>Searching is just as easy.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests

query = <span class="hljs-string">"ai banks"</span>
res = requests.post(
    <span class="hljs-string">"http://localhost:7700/indexes/articles/search"</span>,
    json={<span class="hljs-string">"q"</span>: query}
)
print(res.json())
</code></pre>
<p>The engine returns results in milliseconds. Typo tolerance, word proximity and relevance ranking work out of the box. </p>
<p>Meilisearch automatically handles synonyms if you configure them and allows custom sorting rules for attributes like price or date. It also supports faceting, filters, and geosearch, which makes it suitable for e-commerce, travel apps, real estate listings, and data-heavy dashboards.</p>
<h2 id="heading-using-hybrid-search-and-ai-together">Using Hybrid Search and AI Together</h2>
<p>Hybrid search combines full-text search with semantic vector search. </p>
<p>Meilisearch supports semantic search through vector fields and enables the combination of both approaches. This helps you serve users who type vague queries or natural language questions. </p>
<p>The AI model provides <a target="_blank" href="https://www.ibm.com/think/topics/embedding">embeddings</a> that capture meaning, while Meilisearch handles the fast retrieval and ranking.</p>
<p>To add semantic search, you first generate embeddings for your documents using an AI model. Here is a simple example using OpenAI embeddings:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI
<span class="hljs-keyword">import</span> requests

client = OpenAI()
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">embed</span>(<span class="hljs-params">text</span>):</span>
    out = client.embeddings.create(
        model=<span class="hljs-string">"text-embedding-3-small"</span>,
        input=text
    )
    <span class="hljs-keyword">return</span> out.data[<span class="hljs-number">0</span>].embedding
doc = {
    <span class="hljs-string">"id"</span>: <span class="hljs-number">3</span>,
    <span class="hljs-string">"title"</span>: <span class="hljs-string">"AI in Insurance"</span>,
    <span class="hljs-string">"text"</span>: <span class="hljs-string">"How AI powers underwriting"</span>,
    <span class="hljs-string">"vector"</span>: embed(<span class="hljs-string">"How AI powers underwriting"</span>)
}
requests.put(
    <span class="hljs-string">"http://localhost:7700/indexes/articles/documents"</span>,
    json=[doc]
)
</code></pre>
<p>When the user searches, you embed the query and compute similarity. You can mix this with keyword search results returned from Meilisearch. The combined ranking creates a better experience than either approach alone.</p>
<h2 id="heading-using-ai-to-rewrite-queries">Using AI to Rewrite Queries</h2>
<p>Users often type incomplete or unstructured queries. They might type “How does AI help banks?” instead of keywords. </p>
<p>You can use an AI model to rewrite this into something more search-friendly. The rewritten query produces better results in Meilisearch while still respecting the user’s original intent.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI
<span class="hljs-keyword">import</span> requests

client = OpenAI()
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rewrite_query</span>(<span class="hljs-params">user_query</span>):</span>
    prompt = <span class="hljs-string">f"Rewrite this for search: <span class="hljs-subst">{user_query}</span>"</span>
    out = client.chat.completions.create(
        model=<span class="hljs-string">"gpt-4o-mini"</span>,
        messages=[{<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: prompt}]
    )
    <span class="hljs-keyword">return</span> out.choices[<span class="hljs-number">0</span>].message.content
user_query = <span class="hljs-string">"how does ai help banks"</span>
rewritten = rewrite_query(user_query)
res = requests.post(
    <span class="hljs-string">"http://localhost:7700/indexes/articles/search"</span>,
    json={<span class="hljs-string">"q"</span>: rewritten}
)
print(res.json())
</code></pre>
<p>This pattern improves accuracy for question-based searches across blogs, documentation platforms, and knowledge bases. You can also use the model to normalise queries, remove ambiguous text, expand synonyms, and fix spelling mistakes before they reach Meilisearch.</p>
<h2 id="heading-deploying-meilisearch-to-the-cloud-using-sevalla">Deploying Meilisearch to the Cloud using Sevalla</h2>
<p>You can deploy Meilisearch anywhere. It runs on a small server, a local machine, or inside containers. </p>
<p>Self-hosting gives you full control and is usually preferred by technical teams who want to keep sensitive data in-house. You can choose any cloud provider, like AWS, DigitalOcean, or others to set up Melisearch. But I will be using Sevalla.</p>
<p><a target="_blank" href="https://sevalla.com/">Sevalla</a> is a PaaS provider designed for developers and dev teams shipping features and updates constantly in the most efficient way. It offers application hosting, database, object storage, and static site hosting for your projects.</p>
<p>I am using Sevalla for two reasons:</p>
<ul>
<li><p>Every platform will charge you for creating a cloud resource. Sevalla comes with a $50 credit for us to use, so we won’t incur any costs for this example.</p>
</li>
<li><p>Sevalla has a <a target="_blank" href="https://docs.sevalla.com/templates/overview">template for Melisearch</a>, so it simplifies the manual installation and setup for each resource you will need for installation.</p>
</li>
</ul>
<p><a target="_blank" href="https://app.sevalla.com/login">Log in</a> to Sevalla and click on Templates. You can see Melisearch as one of the templates. Click Deploy. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764079735090/db59a275-f641-4f3a-bae9-c1cab1360cbd.png" alt="Sevalla Template" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You will see the resources being provisioned for the application. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764079768294/8ca6ccbc-2b64-4a3d-984e-f4cd17e19289.png" alt="Sevalla Deployment" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Once the deployment is complete, click on “Visit app”. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764079831010/98be4bbb-6e85-4572-a84e-d11114d1215d.png" alt="Melisearch in Production" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You now have a production-grade Melisearch server running on the cloud. You can use this to set up indexes for your database and use the JavaScript or other SDKs to interact with Melisearch.</p>
<p>Here is the <a target="_blank" href="https://www.meilisearch.com/docs/reference/api/overview">full list of APIs</a> provided by Melisearch. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Meilisearch gives you a fast and elegant base for search. AI models add understanding and personalisation. When these two work together, you get a search experience that feels instant, adaptive, and intelligent. </p>
<p>You can start small with keyword search and then add query rewriting, embeddings, hybrid search, and reranking. You can also use suggestions, synonyms, and filters to improve the user journey. </p>
<p>With its simple API, wide language support, and strong ecosystem, Meilisearch makes it easy to build a search that feels right at home in any modern app.</p>
<p><em>Hope you enjoyed this article. Find me on</em> <a target="_blank" href="https://linkedin.com/in/manishmshiva"><em>Linkedin</em></a> <em>or</em> <a target="_blank" href="https://manishshivanandhan.com/"><em>visit my website</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Real-Time Web Search to Your LLM Using Tavily ]]>
                </title>
                <description>
                    <![CDATA[ Large language models are smart. But they are not always well-informed. They can write code, summarize books, and explain complex topics, but they struggle with real-time facts. Their knowledge ends at their training cutoff, which means they can’t te... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-real-time-web-search-to-your-llm-using-tavily/</link>
                <guid isPermaLink="false">691b909391d8c0f995d8ddc4</guid>
                
                    <category>
                        <![CDATA[ llm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Mon, 17 Nov 2025 21:16:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763414073220/a9ec7f2d-515e-4d1e-9150-a72450d8aec3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Large language models are smart. But they are not always well-informed.</p>
<p>They can write code, summarize books, and explain complex topics, but they struggle with real-time facts.</p>
<p>Their knowledge ends at their training cutoff, which means they can’t tell you what happened last week or even last year.</p>
<p>That’s where web search comes in.</p>
<p>By connecting a model to a search API like <a target="_blank" href="https://www.tavily.com/">Tavily</a>, you can give your LLM access to current, factual information from the internet. This makes your AI assistant, chatbot, or RAG pipeline much more accurate and context-aware.</p>
<p>This guide will show you how to enable real-time web search in your LLM workflow using Tavily and LangChain.</p>
<p>Please note that Tavily is a paid tool (with a generous free tier) and is popular among the Langchain community. I’m not affiliated with the product – it’s just used in a course on AI Agents that I’m taking and seemed like a useful example.</p>
<h2 id="heading-what-well-cover">What We’ll Cover:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-add-web-search-to-an-llm">Why Add Web Search to an LLM</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-tavily-works">How Tavily Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-setting-up-tavily">Setting Up Tavily</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-creating-an-llm-agent-with-tavily-search">Creating an LLM Agent with Tavily Search</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-tavily-search-works">How Tavily Search Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-tavily-without-langchain">Using Tavily Without LangChain</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-improving-search-quality">Improving Search Quality</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-building-a-search-aware-chatbot">Building a Search-Aware Chatbot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-applications">Real-World Applications</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-tavily-is-a-good-fit">Why Tavily Is a Good Fit</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-why-add-web-search-to-an-llm">Why Add Web Search to an LLM?</h2>
<p>When you ask a model a question like “What are the best AI frameworks in 2025?” it tries to predict an answer from its training data. If that data stops in 2023, it might list outdated tools.</p>
<p>By integrating web search, you give the model a way to look things up before answering.</p>
<p>This process is called <a target="_blank" href="https://www.freecodecamp.org/news/retrieval-augmented-generation-rag-handbook/">retrieval-augmented generation</a> (RAG). It combines two steps: retrieving relevant data and generating a response based on it.</p>
<p>Tavily handles the retrieval part. It searches the web for the most relevant content and sends it back as clean, structured summaries that LLMs can easily use. The result is an AI that sounds intelligent and stays accurate.</p>
<h2 id="heading-how-tavily-works">How Tavily Works</h2>
<p>Tavily is a purpose-built web search API designed for AI applications.</p>
<p>Unlike traditional search engines that return links, Tavily returns short, relevant summaries with context. It focuses on delivering concise information that models can understand without complex parsing.</p>
<p>The Tavily API is simple and fast. You can use it directly with Python, Node.js, or through LangChain integrations.</p>
<p>It also supports advanced filtering, topic targeting, and maximum result control to help you fine-tune the amount and quality of retrieved data.</p>
<h2 id="heading-setting-up-tavily">Setting Up Tavily</h2>
<p>First, sign up on tavily.com and get an API key. Tavily is not a free tool but comes with 1000 free credits for us to play with.</p>
<p>Then install the required packages:</p>
<pre><code class="lang-python">pip install -qU langchain langchain-openai langchain-tavily
</code></pre>
<p>Once installed, export your API key so Tavily can authenticate your requests.</p>
<pre><code class="lang-python">export TAVILY_API_KEY=<span class="hljs-string">"your_api_key"</span>
</code></pre>
<p>Now you’re ready to connect Tavily to a language model through LangChain.</p>
<h2 id="heading-creating-an-llm-agent-with-tavily-search">Creating an LLM Agent with Tavily Search</h2>
<p><a target="_blank" href="https://www.turingtalks.ai/p/langchain-vs-langgraph">LangChain</a> makes it easy to combine multiple tools with your model. In this example, we’ll create an agent that uses Tavily as its search backend.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langchain.agents <span class="hljs-keyword">import</span> create_agent
<span class="hljs-keyword">from</span> langchain_openai <span class="hljs-keyword">import</span> ChatOpenAI
<span class="hljs-keyword">from</span> langchain_tavily <span class="hljs-keyword">import</span> TavilySearch

<span class="hljs-comment"># Initialize the Tavily Search tool</span>
tavily_search = TavilySearch(max_results=<span class="hljs-number">5</span>, topic=<span class="hljs-string">"general"</span>)

<span class="hljs-comment"># Initialize the agent with the search tool</span>
agent = create_agent(
    model=ChatOpenAI(model=<span class="hljs-string">"gpt-5"</span>),
    tools=[tavily_search],
    system_prompt=<span class="hljs-string">"You are a helpful research assistant. Use web search to find accurate, up-to-date information."</span>
)
<span class="hljs-comment"># Use the agent</span>
response = agent.invoke({
    <span class="hljs-string">"messages"</span>: [{<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"What is the most popular sport in the world? Include only Wikipedia sources."</span>}]
})
print(response)
</code></pre>
<p>This example creates a conversational agent powered by OpenAI’s GPT model and the Tavily Search tool. The agent reads the user’s query, uses Tavily to fetch relevant web data, and returns an up-to-date answer.</p>
<p>The <code>system_prompt</code> gives the model clear instructions to rely on web results for factual accuracy. You can customise it to limit or expand how much the agent depends on search.</p>
<h2 id="heading-how-tavily-search-works">How Tavily Search Works</h2>
<ol>
<li><p>The user sends a question. The agent receives the message and determines that it needs external information.</p>
</li>
<li><p>Tavily performs a search. It queries the web for relevant results, summarizing content into readable snippets with source links.</p>
</li>
<li><p>The LLM reads the summaries. The model uses these snippets as context and generates a final answer that includes real-world facts.</p>
</li>
</ol>
<p>This pattern transforms your LLM from a static knowledge base into a dynamic assistant that stays current with live data.</p>
<h2 id="heading-using-tavily-without-langchain">Using Tavily Without LangChain</h2>
<p>You can also use Tavily directly with Python if you want more control over the flow.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> tavily <span class="hljs-keyword">import</span> TavilyClient
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

tavily = TavilyClient(api_key=<span class="hljs-string">"your_api_key"</span>)
client = OpenAI()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">answer_with_tavily</span>(<span class="hljs-params">question</span>):</span>
    search_results = tavily.search(question)
    snippets = <span class="hljs-string">"\n"</span>.join([r[<span class="hljs-string">"content"</span>] <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> search_results[<span class="hljs-string">"results"</span>]])
    prompt = <span class="hljs-string">f"Use the following search results to answer the question:\n\n<span class="hljs-subst">{snippets}</span>\n\nQuestion: <span class="hljs-subst">{question}</span>"</span>
    response = client.responses.create(model=<span class="hljs-string">"gpt-4o-mini"</span>, input=prompt)
    <span class="hljs-keyword">return</span> response.output_text
print(answer_with_tavily(<span class="hljs-string">"What are the biggest AI startups of 2025?"</span>))
</code></pre>
<p>This example sends the Tavily search summaries directly into an LLM prompt. It’s simple, flexible, and works even without LangChain.</p>
<h2 id="heading-improving-search-quality">Improving Search Quality</h2>
<p>You can make Tavily results more relevant by adjusting a few parameters.</p>
<ul>
<li><p><strong>max_results:</strong> controls how many snippets to return. Lower values make answers faster and more focused.</p>
</li>
<li><p><strong>topic:</strong> helps narrow down the type of content you want (like “technology”, “science”, or “finance”).</p>
</li>
<li><p><strong>filters:</strong> used to restrict results to certain domains or exclude unwanted ones.</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="lang-python">tavily_search = TavilySearch(max_results=<span class="hljs-number">3</span>, topic=<span class="hljs-string">"technology"</span>)
</code></pre>
<p>This setup tells Tavily to return only the top three tech-related results, ideal for focused queries.</p>
<h2 id="heading-building-a-search-aware-chatbot">Building a Search-Aware Chatbot</h2>
<p>Once you have Tavily connected, you can create a chatbot that automatically uses search when needed.</p>
<p>For example, if a query contains words like “latest”, “today”, or “news”, the agent can trigger a Tavily search.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">smart_chatbot</span>(<span class="hljs-params">question</span>):</span>
    <span class="hljs-keyword">if</span> any(word <span class="hljs-keyword">in</span> question.lower() <span class="hljs-keyword">for</span> word <span class="hljs-keyword">in</span> [<span class="hljs-string">"today"</span>, <span class="hljs-string">"latest"</span>, <span class="hljs-string">"recent"</span>, <span class="hljs-string">"news"</span>]):
        <span class="hljs-keyword">return</span> answer_with_tavily(question)
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> client.responses.create(model=<span class="hljs-string">"gpt-4o-mini"</span>, input=question).output_text
</code></pre>
<p>This makes your chatbot dynamic, using real-time data when necessary, but keeping simple responses fast.</p>
<h2 id="heading-real-world-applications">Real-World Applications</h2>
<p>Search-augmented LLMs are used everywhere.</p>
<p>Research assistants use them to pull recent papers, marketing teams use them to track trends, and analysts use them to gather competitive insights. Developers build knowledge agents that can explore documentation or regulations automatically.</p>
<p>By combining Tavily’s structured search results with an LLM’s reasoning power, you can build tools that stay both accurate and conversational.</p>
<h2 id="heading-why-tavily-is-a-good-fit">Why Tavily Is a Good Fit</h2>
<p>Traditional search APIs return unstructured HTML or raw snippets that models struggle to read.</p>
<p>Tavily is optimized for AI. It cleans, summarizes, and filters data before returning it. The output is concise, readable, and safe to use directly in your prompts or RAG pipelines.</p>
<p>It also reduces <a target="_blank" href="https://www.ibm.com/think/topics/ai-hallucinations">hallucinations</a> because the model has factual, grounded context to work with. This makes it ideal for production AI systems that need reliability as much as creativity.</p>
<p>Tavily is not the only option for web search. There are other options like RAG web browser, Exa, etc. Here is a <a target="_blank" href="https://apify.com/alternatives/tavily-alternatives">full list</a> with their pros and cons.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Large language models are powerful, but they don’t live on the internet. Without search, they guess. With Tavily, they know.</p>
<p>By integrating Tavily into your LLM workflow, you bridge the gap between static intelligence and real-time knowledge. Whether you’re building a chatbot, research tool, or AI assistant, adding Tavily Search gives your model access to the world’s most current information.</p>
<p>The combination of LangChain, OpenAI, and Tavily turns any LLM into a connected, informed, and reliable AI researcher, one that can finally answer questions about today, not just yesterday.</p>
<p><em>Hope you enjoyed this article. Signup for my free newsletter</em> <a target="_blank" href="https://www.turingtalks.ai/"><strong><em>TuringTalks.ai</em></strong></a> <em>for more hands-on tutorials on AI. You can also</em> <a target="_blank" href="https://manishshivanandhan.com/"><strong><em>visit my website</em></strong></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Search Queries in MongoDB ]]>
                </title>
                <description>
                    <![CDATA[ Searching through a database to extract relevant data can be quite cumbersome if you don't have – or know how to use – the right tools. MongoDB is a non-relational, no-SQL database that differs from relational SQL-based databases such as PostgresSQL,... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/optimize-search-queries-in-mongodb/</link>
                <guid isPermaLink="false">66bb58cf074d8d7b12eae398</guid>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 10 Jan 2024 21:12:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/mongosearch.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Searching through a database to extract relevant data can be quite cumbersome if you don't have – or know how to use – the right tools.</p>
<p>MongoDB is a non-relational, no-SQL database that differs from relational SQL-based databases such as PostgresSQL, MySQL.</p>
<p>These SQL-based databases use conventional rows and columns to display data, whereas MongoDB uses collections. Because of this primary distinction, it's important for you to understand certain special terminologies specific to MongoDB.</p>
<p>The inspiration for this tutorial came from working on a personal project. I had to implement a feature which required a complex MongoDB query operation. Scrolling through the MongoDB docs regarding the issue, I got more confused and I couldn’t figure it out.</p>
<p>After consulting several websites and books, I was finally able to get it done. So in this tutorial, my aim is to simplify MongoDB complex search operations for you as a newer MongoDB user.</p>
<p>I hope this article answers your burning questions and helps you navigate through MongoDB query operations.</p>
<p>Before we begin, here are some important prerequisites for this tutorial:</p>
<ul>
<li>Basic knowledge of Node.js</li>
<li>Basic knowledge of MongoDB</li>
<li>Knowledge of MongoDB commands</li>
<li>Knowledge of Postman</li>
</ul>
<h2 id="heading-what-are-mongodb-queries">What Are MongoDB Queries?</h2>
<p>Queries are commands that you use to obtain data from a MongoDB database. They work similarly to the SQL query system, but they operate differently syntax-wise. </p>
<p>A conventional SQL query looks like this:</p>
<pre><code>“SELECT * FROM db.Users”(SQL) vs  “db.collection.find(MONGO DB)”
</code></pre><p>This command lets you get all data stored in the Users database.</p>
<p>Many query operators can be used on a MongoDB database collection to obtain relevant information. But I'll be shedding more light on a few relevant ones in this tutorial.</p>
<h3 id="heading-mongodb-query-examples">MongoDB Query Examples</h3>
<p>Now I'll explain some of the query operators available to you in MongoDB. You can run the code samples provided below in the MongoDB command line interface to see how they work.</p>
<p><code>Find()</code>: This operator returns all the documents in a collection. You can test this out by running;</p>
<pre><code>Db.collection.find()
</code></pre><p>In this case, replace <code>collection</code> with the actual name of the collection you intend to search.</p>
<p><code>findOne()</code>: this query operator returns the first document in a collection that matches the filter attached to the operator.</p>
<pre><code>Db.collection.findOne()
</code></pre><p><code>Aggregate()</code>: This operator collates results from various document in a given collection. You can combine it with other query operators to organize the results and group various data efficiently. </p>
<p>You'll see an example of how to use this operator alongside the limit and sort query operators.</p>
<p><code>limit()</code>: This operator limits the total expected search results to the number specified.</p>
<pre><code>db.collection.aggregate([{ <span class="hljs-attr">$limit</span>: <span class="hljs-number">6</span> }]);
</code></pre><p>This code above limits the total aggregated data to just 6.</p>
<p><code>Sort()</code>: This operator sorts out the findings from the search query in either ascending or descending order.</p>
<pre><code>db.collection.aggregate([
  { <span class="hljs-attr">$sort</span>: { <span class="hljs-attr">fieldName</span>: <span class="hljs-number">1</span> } } <span class="hljs-comment">// Replace 'fieldName' with the actual field name and use 1 for ascending or -1 for descending order</span>
]);
</code></pre><p>You can test these query operators in a standard web application. There are quite a lot of programming tools available to develop applications, but in this tutorial, we'll be using Node.js because it is less complex to use and easily compatible with the MongoDB database application.</p>
<h2 id="heading-how-to-implement-search-queries-in-mongodb-using-nodejs">How to Implement Search Queries in MongoDB using Node.js</h2>
<p>Node.js is a JavaScript-based backend language, and it'll be our go to language for MongoDB usage in this tutorial. </p>
<p>Right now, we'll be writing some code to search documents using the Node.js Express backend framework.</p>
<p>Mongoose will serve as the connection between MongoDB and Node. But before we delve in, what is Mongoose?</p>
<h3 id="heading-what-is-mongoose">What is Mongoose?</h3>
<p>Mongoose is a popular object relational mapping (ORM) tool which helps establish an efficient connection between the database (MongoDB) and the object oriented programming language (Node.js/JavaScript).</p>
<p>It provides extensive features such as data modeling, schema development, model authentication, and data management which simplifies web API and database interactions.</p>
<p>You can also use it to interact with other databases such as Redis, MySQL and Postgres.</p>
<p>Now, let's set up Mongoose.</p>
<pre><code>Npm install mongoose
</code></pre><p>To connect it to MongoDB in a Node.js application, use the following code:</p>
<pre><code><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);

mongoose.connect(<span class="hljs-string">'mongodb://localhost/location'</span>, {
  <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">useUnifiedTopology</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">autoIndex</span>: <span class="hljs-literal">true</span>
})
  .then(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Connected to MongoDB"</span>);
  })
  .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.error(err);
  });
</code></pre><p>This code initiates a connection with the MongoDB database and maintains the connection to allow for data exchange with the backend application.</p>
<h2 id="heading-how-to-search-through-documents-in-mongodb">How to Search Through Documents in MongoDB</h2>
<p>In this section, we'll further improve our search query by applying some of the MongoDB operations we learned in the previous sections. We'll get books in a database based on the <code>findOne</code> parameter we briefly mentioned earlier.</p>
<p>First, let's use the <code>Find()</code> operator like this:</p>
<pre><code>router.get(<span class="hljs-string">"/"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> books = <span class="hljs-keyword">await</span> Book.find();
    res.status(<span class="hljs-number">200</span>).json(books);
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json(err);
  }
});
</code></pre><p>The code above requests all the books in the database. If successfully executed, it returns a status code of 200 with all the books in the collection in JSON format. If unsuccessful, it returns an error code.</p>
<p>How we can apply the <code>Limit()</code> operator like this:</p>
<pre><code>router.get(<span class="hljs-string">"/"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">let</span> limitedBooks = <span class="hljs-keyword">await</span> Book.find().limit(<span class="hljs-number">6</span>);
    res.status(<span class="hljs-number">200</span>).json(limitedBooks);
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json(err);
  }
});
</code></pre><p>This code is quite similar to the code above. But it has an additional limit operator attached which limits the response expected to the first 6 books from the database.</p>
<p>And finally, we'll apply the <code>FindOne()</code> operator:</p>
<pre><code>router.get(<span class="hljs-string">"/"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">let</span> myBook = <span class="hljs-keyword">await</span> Book.findOne({ <span class="hljs-attr">Author</span>: <span class="hljs-string">"Man"</span> });
    res.status(<span class="hljs-number">200</span>).json(myBook);
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json(err);
  }
});
</code></pre><p>In the code above, we tried finding the first book written by someone called “Man”. If it successfully finds that document it will return a success code 200 and the JSON format of that book collection in the database, else it will return an error code.</p>
<h2 id="heading-how-to-search-between-texts-in-mongodb">How to Search Between Texts in MongoDB</h2>
<p>Searching between texts entails a more complex approach to searching a MongoDB database.</p>
<p>It involves searching texts and phrases in the entire database and then displaying the info of objects containing these texts searched.</p>
<p>It is commonly used in complex search operations in order to include only information which is grouped based on price, authors, address, age or any other relevant common variable.</p>
<p>So now, let's implement a special MongoDB search query operator. We'll use this operator to search between texts and return the results as appropriate.</p>
<p>The code for this is displayed below:</p>
<pre><code><span class="hljs-keyword">let</span> myBook = <span class="hljs-keyword">await</span> Book.find({
  <span class="hljs-string">"$or"</span>: [
    { <span class="hljs-attr">Author</span>: { <span class="hljs-attr">$regex</span>: req.params.key } },
    { <span class="hljs-attr">Title</span>: { <span class="hljs-attr">$regex</span>: req.params.key } },
  ]
});
</code></pre><p>This code above utilizes the regex format to help locate phrases in the database and returns it. Regex works on the principle by matching a set of strings with similar patterns. This helps provide a faster response to our search queries and only returns documents that are similar to our search.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. We hope you’ve learnt essentially about MongoDB search queries and how to harness various search operators to obtain the best possible outcomes from your database.</p>
<p>Feel free to drop comments and questions and also check out my other articles <a target="_blank" href="https://www.freecodecamp.org/news/author/oluwatobi/">here</a>. Until next time, keep on coding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Your WordPress Site for Search Engine Visibility ]]>
                </title>
                <description>
                    <![CDATA[ In today's digital landscape, where online presence is key to success, Search Engine Optimization (SEO) plays a pivotal role in driving organic traffic to your website.  Among various content management systems, WordPress is a popular choice due to i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/wordpress-seo/</link>
                <guid isPermaLink="false">66bb57558884c56d5d5638ac</guid>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jim Campbell ]]>
                </dc:creator>
                <pubDate>Thu, 10 Aug 2023 14:55:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/seo-1.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In today's digital landscape, where online presence is key to success, <a target="_blank" href="https://www.freecodecamp.org/news/tag/seo/">Search Engine Optimization (SEO)</a> plays a pivotal role in driving organic traffic to your website. </p>
<p>Among various content management systems, WordPress is a popular choice due to its user-friendly interface and flexibility. </p>
<p>But having a <a target="_blank" href="https://www.freecodecamp.org/news/what-is-wordpress/">WordPress</a> site is just the beginning. Optimizing it for <a target="_blank" href="https://backlinko.com/hub/seo/visibility">search engine visibility</a> is a crucial step toward ensuring your content reaches the right audience. </p>
<p>In this comprehensive guide, we will delve into the key strategies and plugins that can significantly enhance your WordPress website's SEO, enabling it to rank higher on search engine results pages and attract more organic traffic.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/seo.jpeg" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-1-on-page-seo-optimization">1. On-Page SEO Optimization</h2>
<p><a target="_blank" href="https://www.semrush.com/blog/on-page-seo/">On-Page SEO Optimization</a> holds paramount importance for WordPress sites as it lays the foundation for higher search engine rankings, improved user experience, and increased organic traffic. </p>
<p>By meticulously crafting high-quality content, targeting relevant keywords, and optimizing meta tags, WordPress websites become more discoverable by search engines, ensuring that the right audience finds and engages with the content. </p>
<p>Using the proper heading tags, multimedia elements, and logical site structure not only enhances readability for users but also provides search engines with valuable information about the content's relevance and context. </p>
<p>On-Page SEO is the fundamental step that sets the stage for successful online visibility, enabling WordPress sites to establish their authority, credibility, and competitiveness in an ever-expanding digital landscape.</p>
<h3 id="heading-keyword-research-and-analysis">Keyword Research and Analysis</h3>
<p>Effective SEO begins with thorough keyword research and <a target="_blank" href="https://virtualvalley.io/google-competitors-analysis/">Google competitors analysis</a>. Identify the relevant keywords that resonate with your content and target audience. </p>
<p>Utilize <a target="_blank" href="https://influno.com/best-seo-automation-software/">SEO tools</a> such as <a target="_blank" href="https://ads.google.com/intl/en_us/home/tools/keyword-planner/">Google Keyword Planner</a>, <a target="_blank" href="https://www.semrush.com/">SEMrush</a>, or <a target="_blank" href="https://ahrefs.com/">Ahrefs</a> to uncover high-volume and low-competition keywords. These keywords will serve as the foundation for your content creation and optimization efforts.</p>
<h3 id="heading-high-quality-content-creation">High-Quality Content Creation</h3>
<p>Compelling, informative, and unique content is the cornerstone of SEO success. Craft articles, blog posts, and other content that addresses your audience's needs and interests. Utilize proper heading tags (H1, H2, H3, etc.) to structure your content logically. Engage your readers with multimedia elements like images, videos, and infographics. </p>
<p>At <a target="_blank" href="https://campmedia.com">Camp Media</a>, we use an <a target="_blank" href="https://www.shno.co/products/seo-for-solopreneurs">SEO playbook</a>, which involves all of these factors and allows us to be consistent with the process and outsource our best practices to new members of the team.</p>
<h3 id="heading-optimizing-meta-tags">Optimizing Meta Tags</h3>
<p><a target="_blank" href="https://www.semrush.com/blog/meta-tag/">Meta tags</a> are the first interaction users have with your content in search results. </p>
<p>Write enticing title tags that encapsulate the essence of your content while incorporating target keywords. Craft concise and relevant meta descriptions that encourage users to click through to your website. Also, use meta robots tags to control how search engines crawl and index your pages.</p>
<h2 id="heading-2-technical-seo-enhancement">2. Technical SEO Enhancement</h2>
<p>Technical SEO is a vital aspect for WordPress sites, serving as the backbone that supports optimal performance and user experience while ensuring search engines can effectively crawl, index, and rank the website's content.</p>
<p><a target="_blank" href="https://blog.hubspot.com/marketing/how-to-reduce-your-websites-page-speed">A fast-loading website</a>, facilitated by caching plugins and image optimization, not only keeps users engaged but also aligns with search engines' preference for responsive and swift sites, leading to higher rankings. </p>
<p>Mobile responsiveness is no longer an option but a requirement, as search engines prioritize mobile-friendly websites.</p>
<p>Implementing SSL certificates for HTTPS encryption not only enhances user trust but is also recognized as a ranking factor by search algorithms. </p>
<p>Overall, Technical SEO Enhancement guarantees that the technical infrastructure of a WordPress site is robust, efficient, and aligned with search engine guidelines. This ultimately contributes to improved visibility, higher search rankings, and a seamless user experience. </p>
<p>To make your website error-free, you can opt for a <a target="_blank" href="https://www.intelivita.co.uk/seo-services.php">professional SEO services</a> so that experts with technical SEO knowledge can quickly set your site up for success. </p>
<h3 id="heading-website-speed-and-performance">Website Speed and Performance</h3>
<p>Website loading speed is a critical factor for both user experience and SEO. Use caching plugins such as <a target="_blank" href="https://wordpress.org/plugins/wp-super-cache/">WP Super Cache</a> or <a target="_blank" href="https://wordpress.org/plugins/w3-total-cache/">W3 Total Cache</a> to reduce loading times. Optimize images by compressing them without sacrificing quality. Minimize server response time by choosing a <a target="_blank" href="https://www.wpmyweb.com/hosting/best-web-hosting.html">reliable hosting provider</a>.</p>
<h3 id="heading-mobile-responsiveness">Mobile Responsiveness</h3>
<p><a target="_blank" href="https://www.searchenginejournal.com/ranking-factors/mobile-friendliness/">Mobile-friendliness</a> is no longer optional – it's a necessity. Ensure your WordPress theme is responsive, adapting seamlessly to various screen sizes. </p>
<p>Responsive themes provide an optimal user experience on both desktop and mobile devices. Test your site's mobile usability to identify and fix any issues.</p>
<h3 id="heading-ssl-and-website-security">SSL and Website Security</h3>
<p>Website security is not only important for user trust but also for SEO. Implementing an SSL certificate to enable HTTPS on your site not only encrypts data transmission but is also considered a ranking factor by search engines. </p>
<p>Regularly audit your website's security measures and apply updates to prevent vulnerabilities.</p>
<h2 id="heading-3-user-experience-and-accessibility">3. User Experience and Accessibility</h2>
<p><a target="_blank" href="https://www.codeable.io/blog/wordpress-ux/">User Experience (UX)</a> and Accessibility are of paramount importance for WordPress sites as they directly impact how visitors interact with and perceive the content. </p>
<p>A well-designed and intuitive site structure ensures that users can easily navigate through the website, finding the information they need without frustration. </p>
<p>By implementing <a target="_blank" href="https://www.smashingmagazine.com/2009/03/breadcrumbs-in-web-design-examples-and-best-practices/">breadcrumb trails</a>, clear navigation menus, and logical URLs, WordPress sites create a user-friendly environment that encourages longer visits and reduces bounce rates. Also, optimizing for accessibility through features like descriptive alt text for images and semantic HTML ensures that all users, including those with disabilities, can access and understand the content. </p>
<p>Not only does this demonstrate inclusivity and social responsibility, but it also aligns with search engines' emphasis on providing valuable and accessible content to a wide range of users. </p>
<p>Ultimately, prioritizing User Experience and Accessibility within a WordPress site contributes to improved engagement, better search engine rankings, and a positive online reputation.</p>
<h3 id="heading-intuitive-site-structure">Intuitive Site Structure</h3>
<p>A clear and intuitive site structure improves user experience and SEO. Ensure your navigation is logical and user-friendly. Create a <a target="_blank" href="https://rankmath.com/kb/wordpress-permalinks/">URL structure</a> that reflects the hierarchy of your content. Implement breadcrumbs to help users understand their location within your site and navigate back easily.</p>
<h3 id="heading-accessibility-optimization">Accessibility Optimization</h3>
<p>Design your website with <a target="_blank" href="https://wordpress.org/about/accessibility/">accessibility</a> in mind. Ensure your content is accessible to users with disabilities by using semantic HTML. Provide descriptive alt text for images and multimedia to assist screen readers. </p>
<p>Following accessibility guidelines not only benefits users but also enhances your site's search engine visibility.</p>
<h2 id="heading-4-link-building-and-off-page-seo">4. Link Building and Off-Page SEO</h2>
<p>Link Building and Off-Page SEO play a pivotal role in enhancing the authority, credibility, and visibility of WordPress sites in the vast digital landscape. </p>
<p>By acquiring high-quality backlinks from reputable and relevant sources, these websites garner validation from external sources, signaling to search engines that their content is trustworthy and valuable. </p>
<p>Engaging in <a target="_blank" href="https://marketinglad.io/ethical-link-building-strategies/#:~:text=14.,they%20getting%20some%20new%20links.">ethical link building practices</a>, such as guest posting, influencer collaborations, and industry partnerships, not only establishes connections within the online community but also drives referral traffic and expands the site's reach. </p>
<p><a target="_blank" href="https://wpforms.com/social-media-plugins-wordpress/">Social media integration</a> further amplifies the distribution of content, leading to increased engagement and potentially generating more inbound links. </p>
<p>Recognizing that search algorithms consider external signals as a measure of a site's authority, Link Building and Off-Page SEO contribute to higher search rankings, expanded online visibility, and a broader audience reach for WordPress sites.</p>
<h3 id="heading-creating-high-quality-backlinks">Creating High-Quality Backlinks</h3>
<p>Backlinks from authoritative and relevant sources signal to search engines that your content is valuable and trustworthy. Once acquired, it's also crucial to ensure you <a target="_blank" href="https://digitaltriggers.io/the-definitive-guide-to-getting-backlinks-indexed/">get backlinks indexed</a> for them to contribute effectively to your SEO. </p>
<p>Focus on earning backlinks naturally through strategies like guest posting on reputable websites, collaborating with influencers, and participating in industry forums. Avoid questionable practices like buying links or engaging in link farms, as they can lead to penalties.</p>
<h3 id="heading-social-media-integration">Social Media Integration</h3>
<p>Social media plays a significant role in amplifying your content's reach and engagement. Share your articles, blog posts, and other content on various social media platforms (Twitter, Pinterest, Facebook, LinkedIn, and Facebook's new <a target="_blank" href="https://nikolaroza.com/instagram-threads-statistics-facts/">Threads</a>). </p>
<p>Encourage users to share and engage with your content by adding <a target="_blank" href="https://themeisle.com/blog/add-social-share-buttons-to-wordpress/">social sharing buttons</a> to your site. While social signals are not direct ranking factors, increased engagement can indirectly influence SEO.</p>
<h2 id="heading-5-essential-seo-plugins-for-wordpress">5. Essential SEO Plugins for WordPress</h2>
<p>Essential SEO plugins are a cornerstone for optimizing WordPress sites. They offer an array of tools and functionalities that simplify and streamline the complex process of SEO. </p>
<p>Plugins like Yoast SEO and All in One SEO Pack provide invaluable insights and guidance for on-page optimization, ensuring that content is well-structured, keyword-optimized, and equipped with compelling meta tags.</p>
<p>These plugins facilitate the creation of XML sitemaps and breadcrumbs, enabling search engines to efficiently crawl and index the site's content. </p>
<p>Also, caching plugins like WP Super Cache and W3 Total Cache significantly enhance website speed and performance, critical factors for both user experience and search engine rankings. </p>
<p>By integrating these essential plugins, WordPress sites not only save time and effort but also benefit from a comprehensive approach to SEO that contributes to higher visibility, increased organic traffic, and a more competitive online presence.</p>
<h3 id="heading-yoast-seo">Yoast SEO</h3>
<p><a target="_blank" href="https://yoast.com/wordpress/plugins/seo/">Yoast SEO</a> is a widely-used plugin that offers a comprehensive set of tools for on-page optimization. It helps you optimize content by providing real-time analysis of your focus keyword usage, readability, and meta tags. Configure XML sitemaps and breadcrumbs to enhance search engine crawling and user navigation.</p>
<h3 id="heading-all-in-one-seo-pack">All in One SEO Pack</h3>
<p>Similar to Yoast SEO, the <a target="_blank" href="https://wordpress.org/plugins/all-in-one-seo-pack/">All in One SEO Pack</a> plugin provides features for optimizing your content's meta tags, title tags, and meta descriptions. Configure settings for title templates, meta tags, and more. The plugin also offers advanced features suitable for experienced users who want more control over their SEO settings.</p>
<h3 id="heading-wp-super-cache-and-w3-total-cache">WP Super Cache and W3 Total Cache</h3>
<p>As previously mentioned, these caching plugins are essential for enhancing website speed and performance. They create static versions of your pages, reducing server load and improving loading times. </p>
<p>Set up browser caching and object caching to further enhance speed. Minimizing database queries also contributes to a smoother user experience.</p>
<h2 id="heading-6-monitoring-and-continuous-improvement">6. Monitoring and Continuous Improvement</h2>
<p><a target="_blank" href="https://wp-umbrella.com/blog/monitoring-wordpress-the-ultimate-guide/">Monitoring and continuous improvement</a> are essential practices for maintaining the effectiveness and relevance of WordPress sites in the dynamic online landscape. </p>
<p>Regularly tracking key metrics through tools like Google Analytics provides insights into user behavior, site performance, and traffic sources. This data-driven approach enables webmasters to identify trends, understand user preferences, and refine content strategies accordingly. </p>
<p>Google Search Console offers invaluable information about how search engines index and rank the site, allowing for swift identification and resolution of any issues that might affect visibility. </p>
<p>As search algorithms evolve and user expectations change, the ability to adapt is crucial. By consistently monitoring and analyzing data, WordPress sites can ensure they remain aligned with best practices. Ongoing improvements based on insights gleaned from these tools can lead to enhanced user experience, sustained search engine visibility, and continued success in a competitive digital landscape.</p>
<h3 id="heading-google-analytics-integration">Google Analytics Integration</h3>
<p><a target="_blank" href="https://analytics.google.com/analytics/web/">Google Analytics</a> provides invaluable insights into your website's performance, user behavior, and traffic sources. Monitor key metrics such as page views, bounce rates, and user demographics. Analyze this data to refine your content strategy and identify areas for improvement.</p>
<h3 id="heading-google-search-console">Google Search Console</h3>
<p><a target="_blank" href="https://search.google.com/search-console/about">Google Search Console</a> is a powerful tool for monitoring your website's indexing status and search performance. Submit XML sitemaps to ensure search engines crawl and index your content efficiently. Regularly review the index coverage report to identify potential issues and address crawl errors promptly.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, optimizing your WordPress website for search engine visibility is a multifaceted endeavor. It involves a combination of on-page and technical SEO strategies, user experience enhancements, link building efforts, and the integration of essential plugins. </p>
<p>By implementing these strategies and leveraging the power of SEO plugins, you'll be well-equipped to improve your website's ranking on search engine results pages and attract a steady flow of organic traffic. </p>
<p>Remember that SEO is an ongoing process, requiring continuous monitoring, adaptation, and improvement to stay ahead in the ever-evolving digital landscape.</p>
<p>In the fast-paced and competitive online world, optimizing your WordPress website for search engine visibility is not just a choice – it's a necessity. </p>
<p>This comprehensive guide has explored the key strategies and plugins that can significantly enhance your website's SEO, leading to higher rankings, increased organic traffic, and improved user engagement. </p>
<p>By focusing on on-page optimization, technical enhancements, user experience, link building, and utilizing essential SEO plugins, you're setting your website up for success in the digital realm.</p>
<p>Again, remember that SEO is not a one-time task but an ongoing process. The algorithms that search engines use to rank websites are continually evolving, and staying ahead requires dedication and adaptability. </p>
<p>This means you'll need to regularly monitor your website's performance, analyze user behavior, and stay informed about the latest SEO trends and updates. By consistently fine-tuning your strategies, you can ensure your WordPress website remains competitive and visible in search engine results.</p>
<p>Whether you're a seasoned webmaster or a novice WordPress user, the insights shared in this guide provide a solid foundation for optimizing your website and driving meaningful results. </p>
<p>By implementing the practices outlined here, you're not just enhancing your search engine visibility – you're creating a better online experience for your users, fostering trust, and ultimately achieving your goals in the digital landscape. </p>
<p>So, roll up your sleeves, implement these strategies, and watch as your WordPress website climbs the ranks, attracting more organic traffic and achieving the success it deserves.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Google Sheets – How to Make a Dynamic Search Bar ]]>
                </title>
                <description>
                    <![CDATA[ This tutorial is for when CTRL + F is not enough. 🔥 I bet I've used the CTRL + F shortcut more than any other keyboard shortcut in my life. CTRL + Z probably comes close, but I use CTRL + F to find things... 💥ALL 💥 💥💥THE 💥💥 💥💥💥TIME ]]>
                </description>
                <link>https://www.freecodecamp.org/news/dynamic-search-bar-google-sheets/</link>
                <guid isPermaLink="false">66b8dddbfedc3fd92fddb767</guid>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Fri, 02 Jun 2023 13:31:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/Google-Sheets-Dynamic-Search-Bar-with-profile.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This tutorial is for when CTRL + F is not enough. 🔥</p>
<p>I bet I've used the CTRL + F shortcut more than any other keyboard shortcut in my life. CTRL + Z probably comes close, but I use CTRL + F to find things...</p>
<p>💥<strong>ALL 💥</strong></p>
<p>💥💥<strong>THE</strong> 💥💥</p>
<p>💥💥💥<strong>TIME</strong> 💥💥💥</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/more2.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of man saying we need more</em></p>
<p>And yes, it'll work just fine in a Google Sheet to find information.</p>
<p>But sometimes I want to display a range of results based on a word I'm searching for. To do that, we'll create a dynamic search bar in our Google Sheet.</p>
<p>You can also follow along in this walkthrough video:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5xgwvokDhT0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-the-search-bar">The Search Bar</h2>
<p>Our search bar is nothing more than a cell or range of cells. In the example below, it starts in J2.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/google-sheets-search-bar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of a search bar on Google Sheets</em></p>
<p>By adding a <code>=QUERY()</code> function in J5 we can look at whatever is typed into <code>J2</code> (the red circle) and display the search results below it (the blue rectangle).</p>
<p>In my example, I'm searching through a bunch of personal finance transactions (with randomized amounts😀) that are in columns <code>A:F</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/google-sheets-finance-data.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of finance data on Google Sheets</em></p>
<h2 id="heading-the-query-function">The Query Function</h2>
<p>The <code>=QUERY()</code> function looks in the Transactions range (which is that <code>A3:F</code> range where all the transactions live).</p>
<p>And it grabs all the info in either column B or column D that <code>CONTAINS</code> what we type in <code>J2</code>.</p>
<p>So it searches through all our transaction descriptions in column B and categories in column D for whatever we type in <code>J2</code>. The <code>LOWER</code> command turns the info in B and D into lowercase. This makes it easier to search because the <code>CONTAINS</code> command is case-sensitive.</p>
<pre><code class="lang-javascript">=QUERY(Transactions, 
       <span class="hljs-string">"SELECT A,B,C,D,E WHERE LOWER(B) CONTAINS '"</span>&amp;J2&amp;<span class="hljs-string">"' OR LOWER(D) CONTAINS '"</span>&amp;J2&amp;<span class="hljs-string">"'"</span>)
</code></pre>
<ul>
<li>the only caveat is that if you type in uppercase in the search bar, it won't work properly.</li>
</ul>
<h2 id="heading-the-filter-function">The Filter Function</h2>
<p>By using the <code>=FILTER()</code> function in combination with the <code>=SEARCH()</code> function, we can do the same thing in a little bit shorter formula and without having to worry about case sensitivity.</p>
<pre><code class="lang-xls">=<span class="hljs-built_in">IF</span>(<span class="hljs-built_in">ISBLANK</span>(<span class="hljs-symbol">J2</span>),<span class="hljs-string">""</span>,FILTER(Transactions,<span class="hljs-built_in">SEARCH</span>(<span class="hljs-symbol">J2</span>,<span class="hljs-symbol">B3</span>:<span class="hljs-symbol">B225</span>)))
</code></pre>
<p>The tradeoff here is that when we want to add multiple conditions like we did in the <code>=QUERY()</code> statement, it breaks down. Both <code>=FIND()</code> and <code>=SEARCH()</code> did not work properly when trying to use them more than once inside the <code>=FILTER()</code>.</p>
<p>I was able to find a work around by using the plus operator and constructing the formula in this way:</p>
<pre><code class="lang-xls">=<span class="hljs-built_in">IF</span>(<span class="hljs-built_in">ISBLANK</span>(<span class="hljs-symbol">J2</span>),<span class="hljs-string">""</span>,FILTER(Transactions,(<span class="hljs-symbol">B3</span>:<span class="hljs-symbol">B225</span>=<span class="hljs-symbol">J2</span>)+(<span class="hljs-symbol">D3</span>:<span class="hljs-symbol">D225</span>=<span class="hljs-symbol">J2</span>)))
</code></pre>
<p>Unfortunately when you filter in this way, partial matches are not included in the search results. </p>
<p>In the case of Query, partial answers are always returned. </p>
<p>So, when we enter "hom" all the lines with "home" in it would be returned. When using multiple conditions with filter, nothing would return unless you entered the whole word "home".</p>
<h2 id="heading-what-about-xlookup">What About XLOOKUP?</h2>
<p>The issue with XLOOKUP is twofold. One, it doesn't handle partial matches well unless you add wildcard characters:</p>
<pre><code class="lang-xls">=XLOOKUP(<span class="hljs-string">"*"</span>&amp;<span class="hljs-symbol">J2</span>&amp;<span class="hljs-string">"*"</span>,<span class="hljs-symbol">B3</span>:<span class="hljs-symbol">B225</span>,<span class="hljs-symbol">A3</span>:<span class="hljs-symbol">F225</span>,,<span class="hljs-number">2</span>)
</code></pre>
<p>This increases complexity but still works. </p>
<p>The more important difference is that it will only return one result so it's not going to work at all for us for this use case.</p>
<h2 id="heading-the-winner-is-query">The Winner is Query</h2>
<p>Query takes the prize simply because it doesn't need further manipulation to add multiple conditions, and it will return all the values that meet our search criteria.</p>
<p>It may take you a minute to wrap your head around the syntax, but it's just as powerful and more versatile than Filter in the long haul.</p>
<p>The only thing to make sure to remember is case sensitivity. If you're using the <code>LOWER</code> command in your query, don't use any uppercase search letters. </p>
<h2 id="heading-make-it-neat">Make it Neat</h2>
<p>In the full formula, I've added an <code>=IF()</code> function at the start to handle the blank search bar. We want to return nothing in that case:</p>
<pre><code class="lang-xls">=<span class="hljs-built_in">IF</span>(<span class="hljs-built_in">ISBLANK</span>(<span class="hljs-symbol">J2</span>),<span class="hljs-string">""</span>, QUERY(Transactions <span class="hljs-string">"SELECT A,B,C,D,E WHERE LOWER(B) CONTAINS '"</span>&amp;<span class="hljs-symbol">J2</span>&amp;<span class="hljs-string">"' OR LOWER(D) CONTAINS '"</span>&amp;<span class="hljs-symbol">J2</span>&amp;<span class="hljs-string">"'"</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of a blank search bar in Google Sheets</em></p>
<h2 id="heading-follow-along">Follow Along</h2>
<p>Come <a target="_blank" href="https://www.youtube.com/@eamonncottrell?sub_confirmation=1">follow me over on YouTube</a> as I make tutorials each week.</p>
<p><a target="_blank" href="https://got-sheet.beehiiv.com/subscribe">Sign up here</a> to get my newsletter in your email each week.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Beehiivp.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Eamonn's Sheets | Coding | Education logo</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Effectively Search Large Datasets in Python ]]>
                </title>
                <description>
                    <![CDATA[ Imagine you're trying to find a needle in a haystack, but the haystack is the size of a mountain. That's what it can feel like to search for specific items in a massive dataset using Python. But fear not! With the right techniques, you can efficient... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-search-large-datasets-in-python/</link>
                <guid isPermaLink="false">66d4609ff855545810e934c5</guid>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jeremiah Oluseye ]]>
                </dc:creator>
                <pubDate>Mon, 03 Apr 2023 15:08:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/efffe.JPG" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Imagine you're trying to find a needle in a haystack, but the haystack is the size of a mountain. That's what it can feel like to search for specific items in a massive dataset using Python.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/raw--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>But fear not! With the right techniques, you can efficiently search and lookup information in large datasets without feeling like you're climbing Everest.</p>
<p>In this article, I'll show you how to take the pain out of search operations in Python. We'll explore a range of techniques, from using the built-in bisect module to performing a binary search, and we'll even throw in some fun with sets and dictionaries.</p>
<p>So buckle up and get ready to optimize your search operations on large datasets. Let's go!</p>
<h2 id="heading-method-1-linear-search-in-python">Method 1: Linear Search in Python</h2>
<p>The simplest way to search for an item in a list is to perform a linear search. This involves iterating through the list one element at a time until the desired item is found. Here is an example of a linear search:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">linear_search</span>(<span class="hljs-params">arr, x</span>):</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(arr)):
        <span class="hljs-keyword">if</span> arr[i] == x:
            <span class="hljs-keyword">return</span> i
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<p>In the code above, we define the function linear search, which accepts two inputs: a list arr and a single item x. The function loops through the list, iterating through each element and comparing it to the desired item x. The function returns the item's index in the list if a match is found. In the absence of a match, the method returns -1.</p>
<p>Linear search has an O(n) time complexity, where n is the list length. This indicates that the time needed to conduct a linear search will increase proportionally as the size of the list grows.</p>
<h2 id="heading-method-2-binary-search-in-python">Method 2: Binary Search in Python</h2>
<p>If the list is sorted, we can perform a binary search to find the target item more efficiently. Binary search works by repeatedly dividing the search interval in half until the target item is found. Here is an example of a binary search:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_search</span>(<span class="hljs-params">arr, x</span>):</span>
    low = <span class="hljs-number">0</span>
    high = len(arr) - <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> low &lt;= high:
        mid = (low + high) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> arr[mid] &lt; x:
            low = mid + <span class="hljs-number">1</span>
        <span class="hljs-keyword">elif</span> arr[mid] &gt; x:
            high = mid - <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> mid
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<p>In the code above, we define the function binary search, which accepts as inputs a sorted list arr and a target item x. The low and high indices are used by the function to maintain a search interval.</p>
<p>A comparison between the target item x and the middle element of the search interval is performed by the function on each iteration of the loop.</p>
<p>The modified search interval omits the bottom half of the list if the middle element is less than x. The search interval is modified to omit the top half of the list if the middle element is greater than x. The function provides the item's index in the list if the middle element equals x.</p>
<p>If the desired item cannot be located, the function returns -1. Binary search has an O(log n) time complexity, where n is the list length. This means that, especially for big lists, binary search is substantially more effective than linear search.</p>
<h2 id="heading-method-3-search-using-sets-in-python">Method 3: Search Using Sets in Python</h2>
<p>If the order of the list is not important, we can convert the list to a set and use the <code>in</code> operator to check whether an item is present in the set. Here is an example:</p>
<pre><code class="lang-python">my_list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>]
my_set = set(my_list)
<span class="hljs-keyword">if</span> <span class="hljs-number">5</span> <span class="hljs-keyword">in</span> my_set:
    print(<span class="hljs-string">"5 is in the list"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"5 is not in the list"</span>)
</code></pre>
<p>In the above code, we define a list <code>my_list</code> and convert it to a set <code>my_set</code>. We then use the <code>in</code> operator to check whether item 5 is present in the set. If the item is present, we print a message indicating that it is in the list. If the item is not present, we print a message indicating that it is not in the list.</p>
<p>Using sets for search operations can be very efficient for large lists, especially if you need to perform multiple lookups, as sets have an average time complexity of O(1) for the <code>in</code> operator. But sets do not preserve the order of the elements, and converting a list to a set incurs an additional cost.</p>
<h2 id="heading-method-4-search-using-dictionaries-in-python">Method 4: Search Using Dictionaries in Python</h2>
<p>If you need to associate each item in the list with a value or some other piece of information, you can use a dictionary to store the data. Dictionaries provide a fast way to look up a value based on a key. Here is an example:</p>
<pre><code class="lang-python">students = {
    <span class="hljs-string">"John"</span>: <span class="hljs-number">85</span>,
    <span class="hljs-string">"Lisa"</span>: <span class="hljs-number">90</span>,
    <span class="hljs-string">"Mike"</span>: <span class="hljs-number">76</span>,
    <span class="hljs-string">"Sara"</span>: <span class="hljs-number">92</span>,
    <span class="hljs-string">"David"</span>: <span class="hljs-number">87</span>
}
<span class="hljs-keyword">if</span> <span class="hljs-string">"Lisa"</span> <span class="hljs-keyword">in</span> students:
    print(<span class="hljs-string">f"Lisa's grade is <span class="hljs-subst">{students[<span class="hljs-string">'Lisa'</span>]}</span>"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"Lisa is not in the class"</span>)
</code></pre>
<p>In the above code, we define a dictionary <code>students</code> that associates the name of each student with their grade. We then use the <code>in</code> operator to check whether the name "Lisa" is in the dictionary, and if so, we print her grade.</p>
<p>Dictionaries provide an average time complexity of O(1) for lookups based on the key, which makes them very efficient for large datasets. But, dictionaries do not preserve the order of the items, and there is an additional cost associated with creating the dictionary.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Searching and looking up info in large datasets can be a daunting task, but with the right tools and techniques, it doesn't have to be. By applying the methods we've covered in this article, you can efficiently navigate massive datasets with ease and precision.</p>
<p>From the built-in bisect module to the powerful capabilities of sets and dictionaries, Python offers a range of efficient and versatile options for finding and retrieving data. By combining these techniques with smart programming practices and optimization strategies, you can create lightning-fast search operations that can handle even the largest datasets.</p>
<p>So don't let big data intimidate you. With a little bit of creativity, a lot of perseverance, and the techniques we've explored in this article, you can conquer any search challenge and emerge victorious. Happy searching!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Search Files Effectively in the Linux Terminal ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever felt frustrated searching for files manually on your computer? If you’re a developer or DevOps engineer working on GUI-less Linux servers, it'll be hard navigating back and forth to find files. Many people are unaware of the power of Li... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-search-files-in-the-linux-terminal/</link>
                <guid isPermaLink="false">66ba10d5228e16bed602a89f</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Arunachalam B ]]>
                </dc:creator>
                <pubDate>Thu, 09 Feb 2023 22:45:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/02/BB---How-to-search-files-effectively-in-linux.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever felt frustrated searching for files manually on your computer? If you’re a developer or DevOps engineer working on GUI-less Linux servers, it'll be hard navigating back and forth to find files.</p>
<p>Many people are unaware of the power of Linux terminals. Linux has an incredibly powerful command line that allows you to search files and directories in a fraction of a second. </p>
<p>Whether you’re a beginner or an expert, and if you're looking to take your file management skills to the next level, you've arrived at the right spot. This article will help you understand the basics of the most commonly used <strong>find</strong> command in Linux.</p>
<h2 id="heading-what-is-the-find-command-in-linux">What is the <code>find</code> Command in Linux?</h2>
<p>The <code>find</code> command allows you to search for files and directories on your computer. It adds the flexibility to search for files in a specific directory or recursively through all sub-directories.</p>
<p>Let’s explore the power of the <code>find</code> command</p>
<h2 id="heading-how-to-search-a-file-by-name">How to Search a File by Name</h2>
<p>Let’s say you saved a file called <code>hello_world.html</code> somewhere and you don’t even remember the directory name. But your boss is asking you to send them the file immediately.</p>
<p>Usually, if you forgot where you stored a file, you'd begin by going through folder after folder and checking if the file exists. </p>
<p>This is when the <code>find</code> command does a great job. Instead of searching the file manually on your computer, you can use the <code>find</code> command to automate the process.</p>
<p>By passing the name of the file using the <code>-name</code> flag, the <code>find</code> command searches and returns the location of the file.</p>
<pre><code class="lang-bash">find -name &lt;file_name&gt;
</code></pre>
<p><img src="https://lh4.googleusercontent.com/hUG1ogKlPIlvUZZiCIOBO4x1ZTlGAujhGTe2v-KevAi3zU3z-ZuBA0VJvMWht0V-7cLha4beNzMIkENiN0ZiYZfa8Pc0O-XJMzmbfftY_bo9Csrz-4-7dvwJFgC59G94A2GbFpPTkfU6rxL9MrSOCVI" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to search a file by name</em></p>
<p>But remember the <code>-name</code> flag performs a case-sensitive search. If you are looking to do a case-insensitive search, you can use the <code>-iname</code> flag instead.</p>
<pre><code class="lang-bash">find -iname &lt;file_name&gt;
</code></pre>
<p><img src="https://lh4.googleusercontent.com/Gxuso3qZslePPLMxKDtBuQWwQiliDpU2pHAzRTdiRob2OBKrdN1oWA_rTwe2thYiHeUmRo8SBNE2QR6G2kmdDlKhX14wFd9fYmfppZVQNprUHaGMWLB_GgGVSq7l4DQyP2STSFZcx0Rt5B6thvM7T3Y" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to do case-sensitive search</em></p>
<p>You can also use the <code>find</code> command as an alternative to the <code>ls</code> command in some places. Let's assume you need to find all the files ending with the <code>.txt</code> extension. You can do so with the <code>find</code> command using the regex pattern (<code>*.txt</code>).</p>
<pre><code class="lang-bash">find /path/to/search -name <span class="hljs-string">"*.txt"</span>
</code></pre>
<p><img src="https://lh3.googleusercontent.com/xtbCKd-v83ytN4mnr35RbiWCgJuEiAt9LBO_Qq2IDwRPJaQWRfzBUe5YY63JEcLHS344TvGWRzK139n93upgh1ALKgRavsWwNe0iTh772rhGZwFXcpP5eyGz_iI6XPHuDK55Ch93rNe70fSIyJJcMmw" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command displaying file search by matching a pattern</em></p>
<p>This command will list all the <code>.txt</code> files in your current directory and its sub-directories. </p>
<p>To find <code>.txt</code> files in a particular directory and sub-directory, you can replace the <code>/path/to/search</code> with the path of your directory.</p>
<h2 id="heading-how-to-find-a-directory-in-linux">How to Find a Directory in Linux</h2>
<p>Searching for a directory is possible by passing the <code>d</code> to the <code>-type</code> parameter in the <code>find</code> command.</p>
<pre><code class="lang-bash">find /path/to/search -<span class="hljs-built_in">type</span> d
</code></pre>
<p><img src="https://lh5.googleusercontent.com/qmKtQotgBftOfU_pII8GV8gsYJqynmXvaqQIU0VrBOwdcWGwH95R-CQX4rxR3e_xQYyRm5D3bt6f7t0U9DwBHBthlzFnmbtTyvG4MWWMSsOt09zMCTk_ZVcZGUe9NGymbIYf74ELv_7A7yOwY8Hcn0Q" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to search a directory using <code>find</code> command</em></p>
<p>In the above screenshot, we're finding a directory named <code>zip</code> from our current directory.</p>
<p>Similarly the <code>-type</code> option accepts other parameter options to simplify our finding process.</p>
<ul>
<li><code>f</code> finds the list of regular files</li>
<li><code>b</code> finds the list of block devices</li>
<li><code>c</code> finds the list of character devices</li>
<li><code>l</code> finds the list of symbolic links</li>
<li><code>s</code> finds the list of sockets</li>
<li><code>p</code> finds the named pipes</li>
</ul>
<h2 id="heading-how-to-search-a-file-by-size-in-linux">How to Search a File by Size in Linux</h2>
<p>Adding the <code>-size</code> option along with the <code>find</code> command helps you find files based on size. Prepend a <code>+</code> or <code>-</code> to the size to represent greater than and less than, respectively.</p>
<pre><code class="lang-bash">find /path/to/search -size &lt;size_of_the_file&gt;
</code></pre>
<p><img src="https://lh6.googleusercontent.com/5_gYC6AREIU77iDWAOY3uqfyCEPpICXenMzpxMv15oaOyNg2t4QhtH862wZeIRH3IgWxX1MJYwAOMGQZVeerY6HeNYjcmB_bdMiqPnoAsSyQ5JjQ75DqmCOsbcLQ8AeMk31MQb9Z1aC0Q-1CznPNRn8" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to search files by size</em></p>
<p>In the above screenshot, we're finding all the files that have a size greater than 1 GB.</p>
<p>You can also search for all files that fall within a specific size range.</p>
<p>For example, if you want to find all the files that are above 50 MB and below 100 MB, you can run the following command:</p>
<pre><code class="lang-bash">find /path/to/search -size +50M -size -100M
</code></pre>
<p><img src="https://lh6.googleusercontent.com/KylER-ErURtFf22PtpPhqT8yQofvlaA6s7XhP8FdHo4KqLTXYsDY5EL3LhVoyZKrHJGMHYWJ6CheD2PiaS_ynX_x-Ziho5eqK8YbEAqdAVvugE0RUWuOPvuwrUddCIw4TnoqLZDSI2qRak1kdDF6o40" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to search files within a range</em></p>
<p>You can specify the size in your preferred notation. A few of the available notations are:</p>
<ol>
<li>K represents KB</li>
<li>M represents MB</li>
<li>G represents GB</li>
<li>b represents bytes</li>
<li>c represents blocks</li>
</ol>
<h2 id="heading-how-to-search-a-file-based-on-time-modified">How to Search a File Based on Time Modified</h2>
<p>Every file has a created and last updated time associated with it. Let's assume you have thousands of files in your directory. You edited a file in the past couple of days and forgot its name. You're sure that you have edited only a couple of files after that. </p>
<p>In such cases, you can find all the files that were modified within the past 7 days. This limits your search from 1000+ files to a more manageable amount. You'll be able to find the file you edited in seconds after running the command.</p>
<p>This is possible by passing <code>-mtime</code> parameter with the <code>find</code> command.</p>
<pre><code>find /path/to/search -mtime &lt;-number_of_days_ago&gt;
</code></pre><p><img src="https://lh3.googleusercontent.com/EOsirsBvBa83A2NeK1qGZ8g_FLriAngr4yso3nhOpuwT18zrkur92GKfMBfr8nA8ULrgdWvREvzJfSznVecNXZXONs3JXdG3gJFoqZ7PcqFmZe3T2IS0ka-bkSajpj3aXunMvTYYPZkLl4YjkYzx_1Y" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to search file based on modified time</em></p>
<p>Let's assume another scenario, where today's date is February 10, 2023. You modified a file before Feb 3, 2023. After Feb 3, 2023, you modified a lot of files. You have to find the file which you modified before Feb 3, 2023. So, basically, you need the files that were modified before Feb 3, 2023.</p>
<p>Strange scenario, right?</p>
<p>But, you can also run this query using the <code>find</code> command. You can achieve this by exchanging the negative sign (-) with the positive sign (+).</p>
<p>Here's the modified command for you:</p>
<pre><code class="lang-bash">find /path/to/search -mtime +7
</code></pre>
<h2 id="heading-how-to-execute-a-command-on-files-filtered-from-the-find-command">How to Execute a Command on Files Filtered from the <code>find</code> Command</h2>
<p>This question may confuse you. Before revealing the answer, let's understand the question clearly with a real scenario. </p>
<p>Let's assume you have 1000 files in a directory, and running the <code>find</code> command returns 20 matching files. You want to move these 20 files into a different directory. How can you achieve that?</p>
<p>Simply put, we have to run a command over each of the filtered files.</p>
<p>You can do this by passing the <code>-exec</code> option with the <code>find</code> command.</p>
<p>The <code>-exec</code> option executes a command on each file that is found in the search. The <code>-exec</code> option is followed by a command and its arguments, with the <code>{}</code> symbols representing the path of the file being processed.</p>
<p>To represent the end of the <code>-exec</code> command, we have to add <code>\;</code> (a backward slash and a semi-colon).</p>
<p>Here's the syntax:</p>
<pre><code class="lang-bash">find /path/to/search -name  -<span class="hljs-built_in">exec</span>  {}  \;
</code></pre>
<p>Let’s try to move the filtered files from the <code>5minslearn</code> directory to the <code>zip</code> directory.</p>
<p>Here’s the command:</p>
<pre><code>find ./<span class="hljs-number">5</span>minslearn -name <span class="hljs-string">"*.zip"</span> -exec mv {} ./<span class="hljs-number">5</span>minslearn/zip \;
</code></pre><p><img src="https://lh5.googleusercontent.com/Oysc8VJqcheOL0uSk9t18SM1BBckLmZ1Sfs026TByvdQcHNFVDGssztFu13rHi0waaOUXCuKx1rsHbyWCXr190agnVEKZA3rMexuSH_m6myz38JhQ563hNLBKfTBOMklTt-aH5dd05CfXCVwKG0yiZI" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This command searches for all files ending with a <code>.zip</code> in the <code>./5minslearn</code> directory and then moves each file to the <code>./5minslearn/zip</code> directory.</p>
<p>The <code>-exec</code> option allows you to perform a wide range of operations on the files that are found. You can replace the move command from the above example by copying, deleting, or even changing the file permission command.</p>
<h2 id="heading-how-to-execute-a-command-on-files-filtered-with-a-confirmation">How to Execute a Command on Files Filtered with a Confirmation</h2>
<p>Most people will prefer to use this if they're not sure about whether to apply the operation on each file. </p>
<p>The <code>-ok</code> option is similar to the <strong><code>-exec</code></strong> option except that it will ask for confirmation before executing the operation on each file. This command is super helpful to review files that will be affected before executing the specific operation. You also have the option to decline if you're not sure or don't wish to apply the command.</p>
<p>For example, this time let's try to move the <code>.txt</code> files to the other directory.</p>
<pre><code class="lang-bash">find /path/to/search -name <span class="hljs-string">"*.txt"</span> -ok mv {} /path/to/destination \;
</code></pre>
<p><img src="https://lh3.googleusercontent.com/LR9SFYz9f90xR6_aMS_VKEQa7IS9cecwEAMRkNh5KJ1JSMaQCx0cIe-5XOonpOOdELbnU8549XkQ-HfYCQEoG9Epn8F89cA86o3BRFTR9cJtOLM7GgvKpWMNpkutX89sRtWs96wZ0pz-JHZTSGFBrq0" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to move the filtered files with a confirmation</em></p>
<p>The above command searches for all files with a <code>.txt</code> extension in the <code>./5minslearn</code> directory and then prompts the user to confirm before moving each file to the <code>./5minslearn/text_files</code> directory.</p>
<p>To approve the operation, enter <code>yes</code> and <code>no</code> to decline the operation and skip to the next file. </p>
<p>The <code>-ok</code> option is useful when you want to be cautious about the files you are modifying, as it allows you to inspect each file and its location before executing the specified command.</p>
<h2 id="heading-how-to-find-a-file-with-detailed-information">How to Find a File with Detailed Information</h2>
<p>The <code>-ls</code> option in the find command is used to display information about the files found in the search, in the format of the ls command. This option provides detailed information about the files, such as their permissions, owner, size, and last modified time. </p>
<pre><code>find /path/to/search -name <span class="hljs-string">"*.&lt;file-extension&gt;"</span> -ls
</code></pre><p><img src="https://lh4.googleusercontent.com/RYVzpx-YYKuOUhg_lD7RmNKk-PtGodtMIVwL482R6xvItZ40y3dJLdmDCHWEV6EG1kPVfe4NVt3lHgdnzjvr3RD2xs51Sy4NoV584BxhuJCCIO7dGW1x9IXKD8sGEYkZJ6UDcOenwX3F35o2on68SPk" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to list files in <code>ls</code> command format</em></p>
<h2 id="heading-how-to-find-and-remove-files">How to Find and Remove Files</h2>
<p>Have you ever needed to find files and remove them from your computer? The <code>-delete</code> option in the find command does this for you. It allows you to delete files that match the specified criteria.</p>
<pre><code class="lang-bash">find . -name <span class="hljs-string">"*.&lt;extension&gt;"</span> -delete
</code></pre>
<p><img src="https://lh3.googleusercontent.com/W2DQEoEcNi0897Z99NPHyhx6RTPpO1hL0AVCAGCuKdabq8_eXbFtsL2BJdLn6MCqdYXTa7veSRhDj9gTU7Rbbz0vNoIbxF_N_IXmR45IHgH3DMXSnMBRPtLjIKK-G9af5FncqC2s28zqBfP6kcinXqY" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the above example, you can see that the find command deleted the files with the <code>.html</code> extension</p>
<p>Note: This operation is irreversible. Be 100% sure when you run the delete operation.</p>
<p>I would advise running the <code>find</code> command without the <code>-delete</code> flag at first and ensure that only the files that need to be deleted are shown. Once you're sure, you can execute the same command appending <code>-delete</code> flag.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned how to search files effectively using your Linux terminal. </p>
<p>These are very basic options in the find command that I think every developer should know. I believe mastering the fundamentals is the first step to becoming more advanced with Linux. I've been covering basics in all my blogs to help you create a solid foundation. </p>
<p>To learn more about Linux, subscribe to my email newsletter on my <a target="_blank" href="https://5minslearn.gogosoon.com/?ref=fcc_find_command">site</a> and follow me on social media. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Search Functionality to a Ruby on Rails Application ]]>
                </title>
                <description>
                    <![CDATA[ By Sampurna Chapagain Nowadays, most web applications have a search feature. Users can use the search feature in order to navigate websites more easily. Implementing a search feature in Ruby on Rails is very easy. By using only a few lines of code yo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-search-to-ruby-on-rails-app/</link>
                <guid isPermaLink="false">66d460f3c7632f8bfbf1e4b5</guid>
                
                    <category>
                        <![CDATA[ Ruby on Rails ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 13 Jan 2023 18:22:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/markus-winkler-afW1hht0NSs-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sampurna Chapagain</p>
<p>Nowadays, most web applications have a search feature. Users can use the search feature in order to navigate websites more easily.</p>
<p>Implementing a search feature in Ruby on Rails is very easy. By using only a few lines of code you can set it up.</p>
<p>This tutorial assumes that you have basic knowledge of Ruby on Rails. If you need an introduction to the framework, <a target="_blank" href="https://www.freecodecamp.org/news/learn-ruby-on-rails-video-course/">check out this course</a>.</p>
<h3 id="heading-what-will-we-be-creating">What Will We Be Creating</h3>
<p>By the end of this article, we'll have a web app with a search feature that looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/searchresults.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Demo of the app</em></p>
<h2 id="heading-how-to-generate-the-post-scaffold">How to Generate the Post Scaffold</h2>
<p>Here we're using Ruby version 3.0 and Rails version 6.1.7.</p>
<p>Rails scaffold refers to the automatic generation of files that forms the basic structure of the rails project. These files include controllers, views, models, routes, and migration.</p>
<p>Now, let's scaffold the post using the following command:</p>
<p><code>rails g scaffold post title description:text</code></p>
<p>Now, you need to run the migration in order to update the schema using the <code>rails db:migrate</code> command. </p>
<p>If you run the server now, you can perform all the CRUD operations in the project.</p>
<h2 id="heading-how-to-add-haml-to-the-project">How to Add Haml to the Project</h2>
<p>You will be using haml in views instead of erb. You can do this by simply adding <code>gem 'haml', '~&gt; 6.1', '&gt;= 6.1.1'</code> in the gemfile. You can get all gems from the <a target="_blank" href="https://rubygems.org/">https://rubygems.org/</a> website. </p>
<p>Haml uses indentation and its main purpose is to make the markup look beautiful.</p>
<p>Now, you can use the haml extension in views instead of erb. So, you can rename application.html.erb to application.html.haml. You can also use <a target="_blank" href="https://awsm-tools.com/html-to-haml">html to haml tools</a> for converting erb to haml files. </p>
<h2 id="heading-how-to-build-the-search-form">How to Build the Search Form</h2>
<p>Once that's done, you're at the main part of the tutorial. So, let's add the form in the application.html.haml file. </p>
<p>```ruby
%body
    %form{action: "/search"}
      %input{placeholder: "Search",name: "key",type: "text"}
      %button{type: "submit"} Search
    = yield</p>
<p>This code will generate a form in the whole application.</p>
<p>Here, you are passing the action attribute which will redirect to the search page when the form is submitted. Also, you are passing the key as the name attribute for the input element.</p>
<p>If you submit the form now you will get the following routing error:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/searcherror.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Screen recording showing the routing error.</em></p>
<h3 id="heading-how-to-add-root-and-search-routes">How to Add Root and Search Routes</h3>
<p>Let's add a few routes in the routes.rb file.</p>
<p>```ruby
root "posts#index"</p>
<p>get '/search', to: "posts#search"</p>
<p>The first route makes the index view the root page.</p>
<p>The second route adds the search route as a get method. So, you need to create a search action with some SQL queries in the posts controller.</p>
<h3 id="heading-how-to-add-the-search-action-in-the-controller">How to Add the Search Action in the Controller</h3>
<p>In the above route, the search route is looking for search actions in the posts controller. So, let's create it.</p>
<p>```ruby
def search
    key = "%#{params[:key]}%"
    @posts = Post.where("name LIKE ?", key)
end</p>
<p>Here, in the search action, the <code>key</code> variable holds the value of <code>params[:key]</code>. You get the value of <code>params[:key]</code> after the form submission. </p>
<p>The <code>%</code> symbol matches zero, one, or multiple characters. The above code uses two <code>%</code> symbols before and after <code>params[:key]</code> to match the value of <code>params[:key]</code> present in any position with the <code>name</code> column records in the database.</p>
<p>It is using the <code>LIKE</code> operator with a <code>where</code> clause in order to perform a search. <code>?</code> is a placeholder value in queries and gets replaced with whatever arguments get passed – for example, <code>key</code> in this case. </p>
<p>Additionally, you can also use the <code>or</code> operator for searching multiple columns in the database.</p>
<p><code>@posts = Post.where("name LIKE ? or description LIKE ?", key, key)</code></p>
<p>You can search for both the <code>name</code> and <code>description</code> records using the above code. </p>
<h3 id="heading-how-to-add-the-necessary-views">How to Add the Necessary Views</h3>
<p>Next, you need to add a search.html.haml file. But before that, let's create a new partial called _post.html.haml file in order to reuse the code. The post partial will look like this:</p>
<p>```ruby</p>
<p>%tbody
  -@posts.each do |post|
    %tr
      %td= post.name
      %td= post.description
      %td= link_to 'Show', post
      %td= link_to 'Edit', edit_post_path(post)
      %td= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' }
%br/
= link_to 'New Post', new_post_path</p>
<p>This is how the search.html.haml file will look:</p>
<p>```ruby</p>
<p>%h1 Search Results
%p#notice= notice
%h1 Posts
%table
    %thead
        %tr
            %th Name
            %th Description
            %th{colspan: "3"}
    =render "post"</p>
<p>And, you need to update the index.html.haml file as well.</p>
<p>```ruby</p>
<p>%p#notice= notice
%h1 Posts
%table
    %thead
        %tr
            %th Name
            %th Description
            %th{colspan: "3"}
    = render "post"</p>
<p>By doing this, you are using the post partial in both index and search view. </p>
<p>Finally, the search feature works as expected.</p>
<p>You can find the full source code of this project in this <a target="_blank" href="https://github.com/SampurnaC/search_demo_app_fcc">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This is how you can create a search feature in a Rails application. </p>
<p>If you liked this article, please consider <a target="_blank" href="https://www.buymeacoffee.com/SamChapagain">buying me a coffee</a> ☕. </p>
<p>You can find me on <a target="_blank" href="https://twitter.com/saam_codes">Twitter</a> for various content related to Web Development. </p>
<p>Thanks for reading. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Search Works Under the Hood – Data Structures and Search Algorithms Explained ]]>
                </title>
                <description>
                    <![CDATA[ Searching is something people do every day. Whether they're word searching in documents and databases, or pattern matching in bioinformatics to detect anomalies in DNA, the applications for search are pretty much endless. And these applications requi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-searching-works-under-the-hood/</link>
                <guid isPermaLink="false">66c5a2635e24e23ff2251589</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Houssein Badra ]]>
                </dc:creator>
                <pubDate>Wed, 30 Nov 2022 16:33:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/182786404-56a9f6725f9b58b7d00038e0.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Searching is something people do every day. Whether they're word searching in documents and databases, or pattern matching in bioinformatics to detect anomalies in DNA, the applications for search are pretty much endless.</p>
<p>And these applications require a lot of computation. Imagine searching for a particular DNA sequence out of millions, or searching for a user in Google's database. </p>
<p>That's why we need an algorithm that runs very fast without consuming lots of memory. And that's what you'll learn about here.</p>
<p>In this tutorial, we will be diving deep into two famous search algorithms: Rabin-Karp's algorithm and the Knuth-Morris-Pratt algorithm. We'll also discuss their time and space complexity, which is equivalent to the time and space an algorithm consumes, depending on its input size. You will also learn about common data structures for searching.</p>
<p>A very basic knowledge of programming is required to follow along. We'll be using Python examples in this tutorial.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-data-structures-for-bioinformatics-and-searching">Data structures for bioinformatics and searching</a></li>
<li><a class="post-section-overview" href="#heading-naive-search-algorithm">Naïve search algorithm</a></li>
<li><a class="post-section-overview" href="#heading-rabin-karps-algorithm">Rabin-Karp's algorithm</a></li>
<li><a class="post-section-overview" href="#heading-knuth-morris-pratt-algorithm">Knuth-Morris-Pratt algorithm</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-data-structures-for-bioinformatics-and-searching">Data Structures for Bioinformatics and Searching</h2>
<p>Let's first discuss some data structures that you should know even if we weren't diving too deeply into the topic. </p>
<h3 id="heading-the-trie-data-structure">The Trie Data Structure</h3>
<p>A <strong>trie</strong> is a tree-like data structure where each nodes stores a letter of an alphabet. You can structure the nodes in a certain way so that words and strings can be retrieved from the structure by traversing down a branch (path) of the tree.</p>
<p>Let's take the words <strong>ANA</strong>, <strong>AND</strong>, and <strong>BOT</strong> for example – their prefix tree or trie will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Screenshot--80-.png" alt="Image" width="600" height="400" loading="lazy">
<em>How a trie looks like</em></p>
<p>Tries are widely used for:</p>
<ul>
<li>Auto complete</li>
<li>Spell Checkers</li>
<li>Longest prefix matching</li>
<li>Browser history</li>
</ul>
<h3 id="heading-suffix-trees"><strong>Suffix trees</strong></h3>
<p>Suffix trees are tree-based data structures, but instead of taking multiple words to build the tree we will be using the suffixes of a single world. </p>
<p>If we consider the string <strong>AABA</strong>, we will first add a <strong>$</strong> sign to the end of the string. That <strong>$</strong> will make string comparison easier. Now the string is <strong>AABA$</strong>.</p>
<p>We will consider all of it's suffixes and the tree will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Screenshot--82-.png" alt="Image" width="600" height="400" loading="lazy">
<em><strong>A suffix tree</strong></em></p>
<h3 id="heading-burrows-wheeler-transform">Burrows Wheeler transform</h3>
<p>Now we will discuss the burrows wheeler transform which is very useful data structure fort string compression. </p>
<p>This data structure is widely used in bioinformatics for a very specific reason. I want you to imagine a string representing a genome. It maybe very long, like 20 million characters. </p>
<p>But there is actually a way to store genomes efficiently. Imagine the string <strong>AAAAABBBAAA</strong>. This string has many repeats and we can actually compress this string to be something like this: <strong>A5B3A3</strong>. This is very useful for genomes as well which have many repeated characters. </p>
<p>Now let's take the string <strong>BANANA</strong>. We will first add a <strong>$</strong> sign to the start of the string then compute all the cyclic rotations of <strong>$BANANA</strong>. Then will sort the cyclic rotations – and here is the importance of the dollar sign: that value, when sorting, is less than all alphabet values, so it will make sorting way easier. </p>
<p>After we sort the cyclic rotations, the string formed by the last characters of the sorted cyclic rotations is the burrows wheeler transform. It will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Screenshot--83-.png" alt="Image" width="600" height="400" loading="lazy">
<em><strong>Burrows wheeler transform</strong></em></p>
<p>Now as you can see, the burrows wheeler transform tends to have lots of repeats. You might also ask how to reverse the operation. To do that, look at the first characters of the sorted cyclic rotations. They are the same as the characters in the burrows wheeler transform but in sorted order. </p>
<p>So by sorting the burrows wheeler transform, we will get the first and the last letters and compute the original string.</p>
<h2 id="heading-naive-search-algorithm">Naïve Search Algorithm</h2>
<p>Now let's look at a brute force solution for finding a pattern in a string. This approach is not optimal, as it runs with <strong>O(n*m)</strong> time complexity (where m is the length of the pattern and n is the length of the string). </p>
<p>We will consider two pointers, <strong>I</strong> and <strong>J</strong>. First we'll initialize <strong>I</strong> and <strong>J</strong> to be 0. Then we will run a while loop that will keep running while I is less than the length of the string. </p>
<p>Every time the loop runs we will compare the characters at the index <strong>I+J</strong> in the string and the character at the index <strong>J</strong> in the pattern. If they are equal, we will increment <strong>J</strong>, but of mpt. we will increment <strong>I</strong> and reset <strong>J</strong> to be <strong>0</strong>. If j ever exceeds the length of the pattern, then there's a match. </p>
<p>The code for this will look like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">Find_Match</span>(<span class="hljs-params">pattern,string</span>):</span> 

  <span class="hljs-comment">#initialise i and j</span>
  i=<span class="hljs-number">0</span>
  j=<span class="hljs-number">0</span>

  <span class="hljs-keyword">while</span> i&lt;len(string):
   <span class="hljs-keyword">if</span> string[i+j] == pattern[j]:
     j+=<span class="hljs-number">1</span>
   <span class="hljs-keyword">if</span> string[i] != pattern[j]:
     j=<span class="hljs-number">0</span>  
     i+=<span class="hljs-number">1</span>
   <span class="hljs-comment">#Let's say j is equal to the length of the pattern. Then to reach the first match index we can go back a number of steps equal to the length of the pattern.</span>
   <span class="hljs-keyword">if</span> j==len(pattern):
    <span class="hljs-keyword">return</span> i-j

  <span class="hljs-comment">#Incase there is no match  </span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<h2 id="heading-rabin-karps-algorithm">Rabin-Karp's Algorithm</h2>
<p>The problem with the naïve approach is that it runs in O(n**2) time complexity which is horrible when it comes to large inputs like genomes. This means we need something better. </p>
<p>Comparing two strings is linear time, because we need to compare each character for each index. But what if we don't need to do that – what if we transformed the strings into numbers? </p>
<p>Here is the main idea of this algorithm. Let's say there is a function that returns a number associated with each string in the alphabet. We will use the ASCII value of the strings for that. </p>
<p>And then to transform a string into a number we will compute the sum of the ASCII values of all its characters. This a simple hashing function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hash</span>(<span class="hljs-params">string</span>):</span>
 count=<span class="hljs-number">0</span>
 <span class="hljs-comment"># in python ord return the ascii value of a character</span>
 <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> string:
  count+=ord(i)

 <span class="hljs-keyword">return</span> count
</code></pre>
<p>Now let's say we want to find <strong>an</strong> in <strong>banana</strong>. Then we will first compare <strong>hash(an)</strong> to <strong>hash(ba)</strong> then to hash(an) and so on till we reach the end of the string. When the hash values match, we can then compare the pattern and the substring because <strong>hash(na)</strong> and <strong>hash(an)</strong> are equal so we need an extra check.</p>
<p>You might be thinking this is silly – why do we need to do all of this? Computing the hash function needs to iterate over the string so we didn't achieve any better time complexity. And you're completely right. </p>
<p>But what if we can compute the hash value of a substring from its previous substring? The difference is in the starting and ending characters – and that's called a rolling hash. That's what makes this algorithm run at <strong>O(n*m)</strong>  worst case and <strong>O(n+m)</strong> average case: because of collisions. </p>
<p>For example, <strong>hash(na)</strong> is equal to <strong>hash(an)</strong>, so here we need to compare na and an. The hash function I showed you is a very simple one. The better the hash function, the fewer collisions we will have. But I don't want to make this too fancy, so I will be using this hash function.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Screenshot--84-.png" alt="Image" width="600" height="400" loading="lazy">
<em>rolling hash</em></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">Rabin_Karp</span>(<span class="hljs-params">string, pattern</span>):</span>
 <span class="hljs-comment">#compute the hash value of the pattern</span>
 hashed_pattern=hash(pattern)

 <span class="hljs-comment">#compute the hash value of the first substring with length equal to the length of the pattern</span>

 first_hash=hash(string[<span class="hljs-number">0</span>:len(pattern)])

 <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(string)-len(pattern)+<span class="hljs-number">1</span>):
  <span class="hljs-keyword">if</span> i !=<span class="hljs-number">0</span>:
   first_hash-= hash(string[i<span class="hljs-number">-1</span>])
   first_hash+= hash(string[i+len(pattern)<span class="hljs-number">-1</span>])

  <span class="hljs-keyword">if</span> hashed_pattern == first_hash:
   <span class="hljs-comment">#second check</span>
   <span class="hljs-keyword">if</span> pattern == string[i:len(pattern)]:
    <span class="hljs-keyword">return</span> i

 <span class="hljs-comment">#in case no matches are found </span>
 <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<h2 id="heading-knuth-morris-pratt-algorithm">Knuth-Morris-Pratt Algorithm</h2>
<p>Now we will discuss the last algorithm for today. This one is very complicated but I will try to make it as simple as possible. </p>
<p>The idea behind this algorithm is that the naïve approach is great unless the string and the pattern have many repeats – like for example searching for <strong>AAAB</strong> in <strong>AAAXAAA</strong>. In this case do we really need to reset the j pointer to 0 after the first mismatch? Actually no we don't, and I will show you why.</p>
<p>When we analyze this pattern, we can see that it's quite special. Let's say we started at i=0 and we reached j=3. Then the next iteration we got a mismatch. </p>
<p>We don't really need to reset j, since for this given pattern we have the two first characters equal to the second and third characters. And since j already was 3, then the first 3 characters in the string are equal the first three characters in the pattern. And the second and third characters in the string are equal to the first and second characters in the pattern. So we can skip two positions by resetting j to 2 instead of 0.</p>
<p>Now you might ask how we'll know the value of  j after the mismatch. Well, the answer depends on the pattern. For example <strong>abac</strong> if we got a mismatch when we reached j=3 (when we reached c) and since <strong>ab</strong> is equal to <strong>ba</strong>, we can actually skip b for the next iteration. </p>
<p>As you can see this works when we have a common suffix and prefix in a substring of a pattern, so we need to preprocess the string. And for each index of that substring, we can compute the number of skips and store it in an array known as the longest suffix prefix array.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Screenshot--85-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now we'll write the function for computing the <strong>LSP</strong> array. But first I will explain what I will be doing: </p>
<ul>
<li>the first element in the array is always 0</li>
<li>we will create an array LSP with the same length as the pattern</li>
<li>we will have twp pointers i and prevlps. i is an iteration variable initially set to 1, since the first element in the array is always 0. prevlps keeps track of the previous longest prefix suffix.</li>
<li>we will run a while loop which will keep running while i is less then the length of the pattern. It will compare pattern[i] and pattern[prevLps]. If they match, we will set LCP[i] to prevlps +1, and we'll increment i and prevlps by 1.</li>
<li>if they don't match and prevlps was 0 already, we will set LCP[i] to 0 and increment i.</li>
<li>if prevlps was not 0, we will set prevlps to LCP[prevlcp-1].</li>
</ul>
<p>Let's take an example using the string ANAN. First i was 1 and prevlps was 0. The first iteration happens, and A is not equal n and prevlps is 0 – so the LCP is now [0,0,0,0]. </p>
<p>Now for the second iteration we will compare pattern[prevlps] which is A and A which evaluates to true. So now i is 3, prevlps is 1, and LCP is [0,0,1,0]. </p>
<p>And finally, in the final iteration we will compare N and N. The same thing happens as in the past iteration, and LCP is [0,0,1,2]. </p>
<p>The code for LCP is the following:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">LCP</span>(<span class="hljs-params">pattern</span>):</span>
 LCP_array=[<span class="hljs-number">0</span>]* len(pattern)

 i=<span class="hljs-number">1</span>
 prevlcp=<span class="hljs-number">0</span>

 <span class="hljs-keyword">while</span> i&lt;len(pattern):
  <span class="hljs-keyword">if</span> pattern[i]==pattern[prevlcp]:
   LCP_array[i]=prevlcp+<span class="hljs-number">1</span>
   i+=<span class="hljs-number">1</span>
   prevlcp+=<span class="hljs-number">1</span>

  <span class="hljs-keyword">elif</span> prevlcp == <span class="hljs-number">0</span>:
   LCP_array[i]=<span class="hljs-number">0</span>

  <span class="hljs-keyword">else</span>:
   prevlcp=LCP_array[prevlcp<span class="hljs-number">-1</span>]

 <span class="hljs-keyword">return</span> LCP_array
</code></pre>
<p>Now since we have the LCP array we can run the KMP algorithm. It's similar to the naïve algorithm but with some improvements. It will look like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">KMP</span>(<span class="hljs-params">pattern,string</span>):</span> 

  LCP_array=LCP(pattern)

  <span class="hljs-comment">#initialise i and j</span>
  i=<span class="hljs-number">0</span>
  j=<span class="hljs-number">0</span>

  <span class="hljs-keyword">while</span> i&lt;len(string):
   <span class="hljs-keyword">if</span> string[i+j] == pattern[j]:
     j+=<span class="hljs-number">1</span>
   <span class="hljs-keyword">if</span> string[i] != pattern[j]:
     <span class="hljs-comment">#The line that changed</span>
     j=LCP_array[j<span class="hljs-number">-1</span>] 
     i+=<span class="hljs-number">1</span>
   <span class="hljs-comment">#Let's say j is equal to the length of the pattern. Then to reach the first match index we can go back a number of steps equal to tje length of the pattern.</span>
   <span class="hljs-keyword">if</span> j==len(pattern):
    <span class="hljs-keyword">return</span> i-j

  <span class="hljs-comment">#In case there is no match  </span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<p>This algorithm runs with O(n+m) time complexity which is great – but it's little bit complicated. If you noticed, almost nothing changed (just in computing the LCP and a single line changed). This single line is what makes the algorithm so efficient.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In the end I hope you learned something new from this article. We learned about data structures for searching as well as some famous algorithms for searching.</p>
<p>This tutorial was the result of two weeks of research. There are a lot of things that I wanted to cover but I wanted to keep this manageable.</p>
<p>If you found this useful and want to get more awesome content, <a target="_blank" href="https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=&amp;cad=rja&amp;uact=8&amp;ved=2ahUKEwjn_af-zsr7AhX3Q_EDHbA5AqQQFnoECBEQAQ&amp;url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Fhoussein-badra-943879214&amp;usg=AOvVaw09JtGqwagE8pQSOWm7MoPW">follow me on LinkedIn.</a> It will help a lot.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ GitHub Search Tips – How to Search Issues, Repos, and More Effectively on GitHub ]]>
                </title>
                <description>
                    <![CDATA[ When I was a beginner to open-source contributions, one of my greatest challenge was finding the correct projects/issues to work on.  For the longest time I relied on resources curated by different writers on the internet (which were good, by the way... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/github-search-tips/</link>
                <guid isPermaLink="false">66b8dbc7f8e5d39507c4c131</guid>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ open source ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hillary Nyakundi ]]>
                </dc:creator>
                <pubDate>Mon, 17 Oct 2022 19:27:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/Search--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When I was a beginner to open-source contributions, one of my greatest challenge was finding the correct projects/issues to work on. </p>
<p>For the longest time I relied on resources curated by different writers on the internet (which were good, by the way). But I always wanted to find a way around this problem – a way I could search for and track projects that were right for my skill set. </p>
<p>Let's agree on one thing: unlike Google, searching GitHub is not easy. But as a developer, chances are that you'll interacting with GitHub or Gitlab on a daily basis. </p>
<p>Now the question isn't what you use these version control systems for, but how you are using them. Just like mastering Google search skills is essential for any regular internet user, I believe it's also essential for developers to learn how to effectively search GitHub.</p>
<p>In this article we are going to take a look at different techniques you can use to correctly search GitHub. You'll learn how to search through:</p>
<ul>
<li>Issues and Pull Requests</li>
<li>Repositories</li>
<li>Users</li>
<li>Topics</li>
</ul>
<p>And more. Let's get started.</p>
<h2 id="heading-github-search-queries">GitHub Search Queries</h2>
<p>In order to find detailed information about something on the internet, you need to have the correct searching skills. It's not any different with GitHub – to find detailed info you can utilize common filter, sort, and searching techniques to easily find specific issues and pull requests of a given project.</p>
<p>Even though you have multiple resources listed on the internet for different projects, the main problem comes in when you want to do a search by yourself. How do you get started? Which keywords should you use to find the correct results? </p>
<p>Most maintainers tend to label their projects with issues, which makes it easier for contributors to find suitable projects. Listed below are some of the tricks that might help you out  when you are using GitHub.</p>
<h3 id="heading-how-to-search-issues-and-pull-requests-on-github">How to Search Issues and Pull Requests on GitHub</h3>
<p>One of the most common ways of finding projects to contribute to is by searching through issues and related PRs. Here are some tricks you can use to easily find reliable answers:</p>
<ol>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3Abeginner&amp;type=issues">is:issue is:open label:beginner</a></strong> - This particular query will list all projects with issues that are open and labeled <code>beginner</code>.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3Aeasy&amp;type=issues">is:issue is:open label:easy</a></strong> - This will list all open issues that are labeled <code>easy</code>.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3Afirst-timers-only&amp;type=issues">is:issue is:open label:first-timers-only</a></strong> - This lists all open issues that welcome first-timer contributions.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3Agood-first-bug&amp;type=issues">is:issue is:open label:good-first-bug</a></strong> - This lists projects with open issues labeled <code>good-first-bug</code>, to attract contributors to work on them.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22&amp;type=issues">is:issue is:open label:"good first issue"</a></strong> - This will list all open issues with the label <code>good first issue</code>, meaning it is good for place for beginners to get started.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3Astarter&amp;type=issues">is:issue is:open label:starter</a></strong> - This lists all open issues from across GitHub that are labeled <code>starte</code>r.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+label%3Aup-for-grabs&amp;type=issues">is:issue is:open label:up-for-grabs</a></strong> - This lists open issues that are ready to be worked on if you have the necessary skills.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=no%3Aproject+type%3Aissue+is%3Aopen&amp;type=issues">no:project type:issue is:open</a></strong> - This will list all open issues that are not assigned to a specific project.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=no%3Amilestone+type%3Aissue+is%3Aopen&amp;type=issues">no:milestone type:issue is:open</a></strong> - Many times, projects are tracked with milestones. But if you want to find issues that are not tracked, this search query will list those projects for you.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=no%3Alabel+type%3Aissue+is%3Aopen&amp;type=issues">no:label type:issue is:open</a></strong> - This lists all open issues that are not labeled.</li>
<li><strong><a target="_blank" href="https://github.com/search?q=is%3Aissue+is%3Aopen+no%3Aassignee&amp;type=issues">is:issue is:open no:assignee</a></strong> - This shows all open issues that have not yet been assigned to a person.</li>
</ol>
<h3 id="heading-how-to-search-repositories">How to Search Repositories</h3>
<p>By default, to make a search you will type the repository name in the search bar and voilà! You get some search results.</p>
<p>But the chances of you landing on the exact repo you intended are very low. </p>
<p>Let's look at some ways you can narrow down your search:</p>
<h4 id="heading-how-to-find-by-name-descriptionreadme">How to Find by Name, Description/README</h4>
<p>A thing to note when you search by Name and description of the README file is that your search phrase should begin with the <code>in</code> qualifier. This makes it possible to search "inside" what you are looking for.</p>
<p><strong>Example</strong></p>
<ul>
<li><p>Using <code>in:name</code>. Let's say you are looking for resources to learn more about Data Science. In this case, you can use the command <code>Data Science in:name</code> which will list repositories with Data Science in the repository name.</p>
</li>
<li><p>Using <code>in:description</code>. If you want to find repositories with a ceratin description, for example repositories where the term "freeCodeCamp" is included in the descriptionm, our search will be: <code>freecodecamp in:description</code></p>
</li>
<li><p>Using <code>in:readme</code>. You use this to search through a README of a file for a certain phrase. If we want to find repositories where the term freecodecamp is included in the README, our search will be: <code>freecodecamp in:readme</code>.</p>
</li>
<li><p>Using <code>in:topic</code>. You use this to find if a certain phrase or word is labeled in the topics. For example to find all repositories where freecodecamp is listed in the topic, our search will be: <code>freecodecamp in:topic</code></p>
</li>
</ul>
<p>You can also combine multiple search queries to further narrow down the search.</p>
<h4 id="heading-how-to-find-by-stars-forks">How to Find by Stars, Forks</h4>
<p>You can also search for a repository based on how many stars and forks the project has. This makes it easier for you to know how popular the project is.</p>
<p><strong>Examples</strong></p>
<ul>
<li><p>Using <code>stars:n</code>. If you search for a repository with 1000 stars, then your search query will be <code>stars:1000</code>. This will list repositories with exactly 1000 stars. </p>
</li>
<li><p>Using <code>forks:n</code>. This specifies the number of forks a repository should have. If you want find repositories that have less than 100 forks, your search will be: <code>forks:&lt;100</code>.</p>
</li>
</ul>
<p>The good thing is that you can always use relational operators like <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, <code>&gt;=</code> &amp; <code>..</code> to help you further narrow your search. </p>
<h4 id="heading-how-to-find-by-language">How to Find by Language</h4>
<p>Another cool way to search through GitHub is by language. This helps you filter out repositories to a specific language.</p>
<p><strong>Example:</strong></p>
<ul>
<li>Using <code>language:LANGUAGE</code>. For example if you want to find repositories written in PHP, your search will be: <code>language:PHP</code></li>
</ul>
<h4 id="heading-how-to-find-by-organization-name">How to Find by Organization Name</h4>
<p>You can also search repositories/projects that are maintained or created by a specific organization. For this you need to begin your search with the keyword <code>org:...</code> followed by the organization name.</p>
<p>For example if you search <code>org:freecodecamp</code> it will list repositories that match freeCodeCamp.</p>
<h4 id="heading-how-to-find-by-date">How to Find by Date</h4>
<p>If you want your results based on a specific date, you can search using one of these keywords: <code>created</code>, <code>updated</code>, <code>merged</code> and <code>closed</code>. These keywords should be accompanied by date in the format <code>YYYY-MM-DD</code>.</p>
<p><strong>Example:</strong></p>
<ul>
<li>Using <code>keyword:YYYY-MM-DD</code>. Take an instance where we want to make a search of all repositories with the word freeCodeCamp that were created after 2022-10-01. Then our search will be: <code>freecodecamp created:&gt;2022-10-01</code></li>
</ul>
<p>You can also use <code>&lt;</code>, <code>&gt;</code>, <code>&gt;=</code> and <code>&lt;=</code> to search for dates after, before and on the specified date. To search within a range you can use <code>...</code>.</p>
<h4 id="heading-how-to-find-by-license">How to Find by License</h4>
<p>Licenses are very important when you are are looking for a project to contribute to. Different licenses give different rights as to what a contributor can do or can not do. </p>
<p>To make it easier for you to find projects with right licenses you need to have a good understanding of licenses. You can read more about them <a target="_blank" href="https://www.freecodecamp.org/news/how-open-source-licenses-work-and-how-to-add-them-to-your-projects-34310c3cf94/">here</a>.</p>
<p><strong>Example:</strong></p>
<ul>
<li>Using <code>license:LICENSE_KEYWORD</code>. This is a good way to search for projects with specific licenses. To search projects with the MIT license, for instance, you would do <code>license:MIT</code>.</li>
</ul>
<h4 id="heading-how-to-find-by-visibility">How to Find by Visibility</h4>
<p>You can also conduct your search in terms of the visibility of the repository. In this case you can either use public or private. This will match issues and PRs that are either in a public or private repository, respectively.</p>
<p><strong>Examples:</strong></p>
<ul>
<li>Using <code>is:public</code>. This will show a list of public repositories. Let's take an isntance where we want to search all public repositories owned by freeCodCamp. Then our search will be: <code>is:public org:freecodecamp</code>.</li>
<li>Using <code>is:private</code>. This query is meant to lists all private repositories under the given search query.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Even though we have covered many search queries here, you can always be creative to further narrow your search by combining multiple parameters together. </p>
<p>For additional resources and more search parameters, you can always refer to the <a target="_blank" href="https://docs.github.com/en/search-github/searching-on-github">GitHub Docs</a> or make use of <a target="_blank" href="https://github.com/search/advanced?">Advanced GitHub Search</a>. These methods will always come in handy as they offer more filering options.</p>
<p>There are a ton of search parameters you can use to make your daily activity around GitHub easier. Hopefully this will help you use the platform more easily and effectively.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Google like a Pro – 10 Tips for More Effective Googling ]]>
                </title>
                <description>
                    <![CDATA[ Pretty much everything is available on the internet, and Google is one of the main ways people search for information.  And while you might think it's obvious, many internet users don't know how to use Google search efficiently and effectively. In tr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-google-like-a-pro-10-tips-for-effective-googling/</link>
                <guid isPermaLink="false">66ba5d46e5ad5bacb410af20</guid>
                
                    <category>
                        <![CDATA[ Google ]]>
                    </category>
                
                    <category>
                        <![CDATA[ research ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham De Roy ]]>
                </dc:creator>
                <pubDate>Fri, 12 Aug 2022 18:19:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/Group-61.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Pretty much everything is available on the internet, and Google is one of the main ways people search for information. </p>
<p>And while you might think it's obvious, many internet users don't know how to use Google search <strong>efficiently</strong> and <strong>effectively</strong>.</p>
<p>In truth, Googling is an art. </p>
<p>To get the right answers, you need to ask the right questions. And to get the right answers quickly, you must know <strong>how</strong> to ask the right questions. </p>
<p>Everyone should learn the <strong>how</strong> part, and that's what this tutorial is all about. Below are some helpful tips and tricks you can use to find correct answers to your questions effectively and efficiently.</p>
<h2 id="heading-how-to-search-google-effectively">How to Search Google Effectively</h2>
<h3 id="heading-1-use-quotes-to-get-an-exact-match">1. Use quotes to get an "EXACT" match</h3>
<p>Generally, when we do a regular search on Google, it makes a <strong>shallow</strong> search. This may result in pages that may or may not contain all the words you mentioned in your search query. </p>
<p>But if you wrap your search query or question (either a term or a phrase) in quotes like this: <code>"your question goes here"</code> then Google will do a deep search. This means that all the results will include pages that <strong>contain all the terms</strong> in your question that you put within quotes. </p>
<p>This is helpful when you absolutely want a particular term or phrase to be there in your search results.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img1.PNG" alt="img1" width="600" height="400" loading="lazy"></p>
<h3 id="heading-2-search-within-a-specific-site-with-site">2. Search within a specific site with <code>site:</code></h3>
<p>If you want Google to return results from within a particular website, just add <code>site:</code> before the question you are searching. </p>
<p>This is also helpful when you want to search for something within a website that doesn't have an internal search option or perhaps doesn't have a very effective one. </p>
<p>For example, searching for <strong>site:freecodecamp.org react</strong> will populate search results only from the <a target="_blank" href="https://www.freecodecamp.org/">www.freecodecamp.org</a> website on the topic of React.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img2.PNG" alt="img2" width="600" height="400" loading="lazy"></p>
<h3 id="heading-3-exclude-a-term-from-search-results-with">3. Exclude a term from search results with <code>-</code></h3>
<p>If you don't want a term or phrase to appear in your search results, then just add <code>-</code> in front of that word. </p>
<p>For e.g. a search on =&gt; <strong>how to write components in React -class</strong> will return all the search results that don't have the term "class" in them. So, (if you know a bit of React) it'll give you only ways to write functional components in React.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img3.PNG" alt="img3" width="600" height="400" loading="lazy"></p>
<h3 id="heading-4-search-images-of-a-particular-size-with-imagesize">4. Search images of a particular size with <code>imagesize:</code></h3>
<p>If you want to search images of a particular size, then use the tag <code>imagesize:</code> in your search query along with the width and height in <strong>pixels</strong>. </p>
<p>Dimension should be in <strong>pixels</strong> only – for example, <code>imagesize:500x500</code> will populate image results which have a dimension of 500px x 500px. So a search on =&gt; "cute dog images imagesize:500x600" (coz why not) will result in pictures of cute dogs with an image size of <code>500px x 600px</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img4.PNG" alt="img4" width="600" height="400" loading="lazy"></p>
<h3 id="heading-5-search-for-a-particular-filetype-with-filetype">5. Search for a particular filetype with <code>filetype:</code></h3>
<p>If you want to get search results that contain a particular file type such as PDF or PPT, then add <code>filetype:&lt;extension&gt;</code> (without the angular brackets). For example, <strong>react tutorial filetype:pdf</strong> will generate results that contains PDF in them, as seen in the following image:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img5.PNG" alt="img5" width="600" height="400" loading="lazy"></p>
<h3 id="heading-6-use-wildcard-to-make-searches">6. Use wildcard <code>*</code> to make searches</h3>
<p>If you are unsure about or have forgotten any term in your search query/ question, then use the wildcard <code>*</code> charachter. Google will replace it for you with relevant terms. </p>
<p>For example, a search on =&gt; the <em> of money will populate the following results. It will be a bunch of pages that include the phrase such as "the </em>exchange<em> of money", "the </em>use<em> of money", "the </em>role<em> of money", "the </em>psychology* of money", and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img6.PNG" alt="img6" width="600" height="400" loading="lazy"></p>
<h3 id="heading-7-combine-searches-with-or-and-logic">7. Combine searches with <code>OR</code>, <code>AND</code> logic</h3>
<p>If you want your search results to contain two terms, then put the <code>AND</code> keyword in between them. For example, the search on =&gt; <strong>React AND Angular</strong> will fetch results that have both the terms react and angular in it. </p>
<p>Similarly, if you want either of the terms in your search results, then use the <code>OR</code> keyword in between them. For example, the search on =&gt; <strong>React OR Angular</strong> will fetch results that have either of the terms or even both.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img7.PNG" alt="img7" width="600" height="400" loading="lazy"></p>
<h3 id="heading-8-filter-out-searches-with-after-before-or-between-two-numbers">8. Filter out searches with <code>AFTER:</code>, <code>BEFORE:</code> or <code>..</code> between two numbers</h3>
<p>If you want Google to populate search results that were published after a particular year, then use the tag <code>AFTER:</code>. For example, the search on =&gt; <strong>React tutorials AFTER:2020</strong> will populate search results published after 2020. </p>
<p>Similarly adding the tag <code>BEFORE:</code> will return results published before a particular year. </p>
<p>You can also search for results published in a certain year range, or for that matter between any numbers. Just add <code>..</code> between the two numbers you want to search between along with the units, if any.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img8.PNG" alt="img8" width="600" height="400" loading="lazy"></p>
<h3 id="heading-9-check-out-related-websites-using-related">9. Check out related websites using <code>related:</code></h3>
<p>If you want to know what all other websites are available on the internet that are similar to a particular website, then use the <code>related:</code> tag. </p>
<p>For example, a search on <strong>related:google.com</strong> will fetch all the websites that are similar to Google like Bing, Yahoo, DuckDuckGo, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img9.PNG" alt="img9" width="600" height="400" loading="lazy"></p>
<h3 id="heading-10-use-cache-to-see-googles-cached-version-of-a-website">10. Use <code>cache:</code> to see Google's cached version of a website</h3>
<p>Google stores a cached version of websites to provide search results quickly. To see if Google has cached any site or not, just use the tag <code>cache:</code> in front of the website's URL. </p>
<p>This is especially helpful for <strong>web developers</strong> if they want to check if they are currently viewing a cached site or the latest version of a website after they have pushed some changes to the website. For example, a search for =&gt; <strong>cache:www.sohamderoy.dev</strong> on the day of writing this tutorial (that is, 4th Aug 2022) returns the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/img10a.png" alt="img10a" width="600" height="400" loading="lazy"></p>
<p>As you see, even though I am searching for the site on 4th August 2022, I still see a copy of the site from 3rd August 2022, as that is when Google has cached the website.</p>
<p>It is important to note that "Not all search operators return exhaustive results." as mentioned by <a target="_blank" href="https://support.google.com/websearch/answer/2466433?visit_id=637790664879774647-1036329470&amp;p=adv_pages_similar&amp;hl=en&amp;rd=1">Google</a> itself. </p>
<p>Still, I believe that these are some really handy tips that help you make an effective and efficient Google search. I hope I've explained them properly and have encouraged you to use them in your regular Google search.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Thanks for reading! I really hope you enjoyed reading this short article about how to google efficeiently and effectively and found this tutorial useful. </p>
<p>Do consider sharing it with your friends – I'd really appreciate that. Follow me on LinkedIn and Twitter and stay tuned for more amazing content! Peace out! 🖖</p>
<h3 id="heading-social-links">Social Links</h3>
<ul>
<li><a target="_blank" href="https://www.linkedin.com/feed/">LinkedIn</a></li>
<li><a target="_blank" href="https://www.sohamderoy.dev/">Website</a></li>
<li><a target="_blank" href="https://blogs.sohamderoy.dev">Other Blogs by me</a></li>
<li><a target="_blank" href="https://twitter.com/_sohamderoy">Twitter</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Google – Search Tips for Better Results ]]>
                </title>
                <description>
                    <![CDATA[ By Marko Denic Google is the most powerful tool in the world if you know how to use it properly. Let me show you how to get better at Googling. 1. Use Quotes for Exact-Match Search You can use quotes to force an exact-match search. This is super usef... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-google-search-tips/</link>
                <guid isPermaLink="false">66d45e00787a2a3b05af439a</guid>
                
                    <category>
                        <![CDATA[ Google ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 29 Mar 2022 18:21:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/pexels-photomix-company-218717.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Marko Denic</p>
<p>Google is the most powerful tool in the world if you know how to use it properly. Let me show you how to get better at Googling.</p>
<h2 id="heading-1-use-quotes-for-exact-match-search">1. Use Quotes for Exact-Match Search</h2>
<p>You can use quotes to force an exact-match search. This is super useful if you know exactly the search phrase you're looking for. You'll simply get more accurate results if you do this.</p>
<p><code>"what is javascript"</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-exact.PNG" alt="Google search exact match example" width="600" height="400" loading="lazy"></p>
<h2 id="heading-2-use-the-and-operator">2. Use the AND Operator</h2>
<p>The AND operator will return only results related to both terms. In the example bellow you can see the perfect use-case of this operator.</p>
<p><code>html AND css</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-and.PNG" alt="Google search with AND keyword" width="600" height="400" loading="lazy"></p>
<h2 id="heading-3-use-the-or-operator">3. Use the OR Operator</h2>
<p>You can use the OR operator to get results related to one of the search terms you enter.</p>
<p><code>(javascript OR python) free course</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-or.PNG" alt="Google search OR keyword example" width="600" height="400" loading="lazy"></p>
<h2 id="heading-4-use-the-minus-operator">4. Use the - (minus) Operator</h2>
<p>The - operator will exclude results that contain a term or phrase. So, in our case we want to get JavaScript related results, but exclude any CSS results from them.</p>
<p><code>javascript -css</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-minus.PNG" alt="Google search with - operator example" width="600" height="400" loading="lazy"></p>
<h2 id="heading-5-use-wildcards-as-placeholders">5. Use (*) wildcards as placeholders</h2>
<p>You can use the (*) wildcards as placeholders, which will be replaced by any word or phrase. </p>
<p>This one is my favorite. I use it when I know almost the whole search phrase and just replace the part I don't know with asterisk. Super useful.</p>
<p><code>"how to start * in 6 months"</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-wildcard.PNG" alt="Google search with wildcard example" width="600" height="400" loading="lazy"></p>
<h2 id="heading-6-how-to-search-inside-a-single-website">6. How to Search Inside a Single Website</h2>
<p>This is another one I use frequently. If I'm searching for something in particular on a specific website, this is my approach.</p>
<p><code>site:freecodecamp.org</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-site.PNG" alt="Google search inside a single website example" width="600" height="400" loading="lazy"></p>
<h2 id="heading-7-how-to-find-a-specific-file-type">7. How to Find a Specific File Type</h2>
<p>You can also use this very useful feature to help you find a specific file type. It's handy if you're looking for some materials like PDFs. If you haven't used it before, from now on you will.</p>
<p><code>filetype:pdf learn css</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-filetype.PNG" alt="Google search for specific filetype" width="600" height="400" loading="lazy"></p>
<h2 id="heading-8-how-to-search-for-a-range-of-numbers">8. How to Search for a Range of Numbers</h2>
<p>This can be anything at all. If you're looking to buy something that falls within a specific price range, or you're searching for results that include a specific range of years, this is for you.</p>
<p><code>ecmascript 2016..2018</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-range.PNG" alt="Google search for specific range of numbers" width="600" height="400" loading="lazy"></p>
<h2 id="heading-9-use-the-before-operator">9. Use the <code>before</code> Operator</h2>
<p>Use the before operator to return only results before a given date.<br>You must provide year-month-day dates or only a year. For example:</p>
<p><code>javascript before:2020</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-before.png" alt="Google search with before operator" width="600" height="400" loading="lazy"></p>
<h2 id="heading-10-use-the-after-operator">10. Use the <code>after</code> Operator</h2>
<p>Use the after operator to return only results after a given date. You must provide year-month-day dates or only a year. Super useful if you want exclude outdated results.</p>
<p><code>web development after:2020</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/google-after.png" alt="Google search with after operator" width="600" height="400" loading="lazy"></p>
<p>As you can see, Google can be a powerful tool if you know how to use it properly. </p>
<p>If you have any questions, you can contact me on <a target="_blank" href="https://twitter.com/denicmarko">Twitter</a>.</p>
<p>You can find a ton of real-life tips and resources on my <a target="_blank" href="https://markodenic.com/blog/">blog</a>. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Search Functionality to a Frontend Application ]]>
                </title>
                <description>
                    <![CDATA[ By Njoku Samson Ebere As a software developer, part of your job is to deliver the best user experience possible to those using your site or product.  And building a helpful and efficient search function is one way you can do this. So if you are looki... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-search-to-frontend-app/</link>
                <guid isPermaLink="false">66d84f9b5e1ebbdb6468edcd</guid>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 04 Jan 2022 16:28:58 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/01/pexels-ketut-subiyanto-4126712.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Njoku Samson Ebere</p>
<p>As a software developer, part of your job is to deliver the best user experience possible to those using your site or product. </p>
<p>And building a helpful and efficient search function is one way you can do this. So if you are looking for the right way to build out search functionality on the front end of your site, you're in the right place. </p>
<p>Some time ago, I thought that search functionality had to be built in the back end and called from the front end. </p>
<p>But as I continued building applications, I learned that sometimes, you might just have to search among the data retrieved from a public endpoint where there is no <em>search</em> endpoint. Other times, frontend search might be necessary to improve a website’s speed and user experience in general.</p>
<p>This tutorial will first go through the "wrong way" of setting up search which many of us have adopted. And then we'll learn a much better way of doing it. So stick with me and let me take you on this ride.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>It will be easy to follow this tutorial if you have basic knowledge of:</p>
<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">JavaScript</a></li>
<li><a target="_blank" href="https://reactjs.org/">React</a></li>
</ul>
<h2 id="heading-starter-project">Starter Project</h2>
<p>I have cooked up a little application to give you a head-start if you want to code along with me. Just clone <a target="_blank" href="https://github.com/EBEREGIT/search-tutorial/tree/starter-code">this repository</a>. The branch of interest is the <strong>starter-code</strong> branch. </p>
<p>Follow the instructions in the <a target="_blank" href="https://github.com/EBEREGIT/search-tutorial/blob/starter-code/README.md">ReadMe</a> file to setup the project and you should have the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/Screenshot-2021-12-29-at-20.17.12.png" alt="Image" width="600" height="400" loading="lazy">
<em>Starter Project Screen</em></p>
<p>In the project you now have, we are fetching COVID-19 updates for every country in the <code>src/context/hatchways.js</code> file courtesy of <a target="_blank" href="https://api.coronatracker.com/">coronatracker</a>. </p>
<p>In our <code>src/App.js</code> file, we display the results we have gotten. A <em>search</em> input box is situated above the list of results. For each of these result, the <code>src/components/Country.js</code> file is rendered.</p>
<p>As a user types into the input box, the <code>filterCountryByName</code> function is called to search through the countries we collected earlier. This function is being built in the <code>src/Helpers/HatchHelper.js</code> file.</p>
<p>All styles are in the <code>src/styles/App.scss</code> file.</p>
<p>You should now be able to navigate around the project and find your way. Let's begin with how you shouldn't build out your search functionality.</p>
<h2 id="heading-how-not-to-build-search-functionality">How NOT to Build Search Functionality</h2>
<p>We will focus on the <code>src/Helpers/HatchHelper.js</code> file to build out the search function.</p>
<p>Already we have the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// search countries by name</span>
<span class="hljs-keyword">const</span> filterCountryByName = <span class="hljs-function">(<span class="hljs-params">name, countries, setResults</span>) =&gt;</span> {
  <span class="hljs-comment">// clear search result if the search field is empty</span>
  <span class="hljs-keyword">if</span> (name === <span class="hljs-string">""</span>) {
    setResults([]);
  }

  <span class="hljs-comment">// discontinue if there is no search yet</span>
  <span class="hljs-keyword">if</span> (name === <span class="hljs-literal">null</span> || name === <span class="hljs-string">""</span> || countries === []) <span class="hljs-keyword">return</span>;
};
</code></pre>
<p>Next, we need to empty the previous search array so that we don't add the new search result to it. This is just in case we already made a search and want to do another.</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// empty the previous search array if any</span>
    <span class="hljs-keyword">const</span> searchResult = [];
</code></pre>
<p>Convert the <em>search string</em> to lower case for consistency's sake. This will make the search case insensitive.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> data = name.toLowerCase();
</code></pre>
<p>Now, loop through the <strong>countries</strong> like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// loop through all countries</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> country <span class="hljs-keyword">of</span> countries) {

  }
</code></pre>
<p>Next, collect each country name and make it lower case to ensure that the search will be case insensitive like so:</p>
<pre><code class="lang-javascript">    <span class="hljs-keyword">const</span> countryName = country.countryName.toLowerCase();
</code></pre>
<p>Below that, check if the search string matches one character in the country name (<code>[...countryName].includes(data)</code>), one word in the country name (<code>countryName.split(" ").includes(data)</code>) or the full country name (<code>countryName === data</code>) and collect the country details like so:</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// check if the search word or character matches</span>
    <span class="hljs-keyword">if</span> (
      [...countryName].includes(data) ||
      countryName === data ||
      countryName.split(<span class="hljs-string">" "</span>).includes(data)
    ) {
      searchResult.push(country);
    }
</code></pre>
<p>When the loop is done, update the search Result with the following line of code:</p>
<pre><code class="lang-javascript">setResults(searchResult);
</code></pre>
<p>The <code>filterCountryByName</code> function now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// search countries by name</span>
<span class="hljs-keyword">const</span> filterCountryByName = <span class="hljs-function">(<span class="hljs-params">name, countries, setResults</span>) =&gt;</span> {
  <span class="hljs-comment">// clear search result if the search field is empty</span>
  <span class="hljs-keyword">if</span> (name === <span class="hljs-string">""</span>) {
    setResults([]);
  }

  <span class="hljs-comment">// discontinue if there is no search yet</span>
  <span class="hljs-keyword">if</span> (name === <span class="hljs-literal">null</span> || name === <span class="hljs-string">""</span> || countries === []) <span class="hljs-keyword">return</span>;

  <span class="hljs-comment">// empty the previous search array if any</span>
  <span class="hljs-keyword">const</span> searchResult = [];
  <span class="hljs-keyword">const</span> data = name.toLowerCase();

  <span class="hljs-comment">// loop through all countries</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> country <span class="hljs-keyword">of</span> countries) {
    <span class="hljs-keyword">const</span> countryName = country.countryName.toLowerCase();

    <span class="hljs-comment">// check if the search word or character matches</span>
    <span class="hljs-keyword">if</span> (
      [...countryName].includes(data) ||
      countryName === data ||
      countryName.split(<span class="hljs-string">" "</span>).includes(data)
    ) {
      searchResult.push(country);
    }
  }

  setResults(searchResult);
};
</code></pre>
<p>Replace the <strong>main</strong> element in the <code>src/App.js</code> file with the following code to ensure proper feedback during search:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
    {filterByNameResults &amp;&amp; filterByNameResults.length
    ? filterByNameResults.map((country) =&gt; (
    <span class="hljs-tag">&lt;<span class="hljs-name">Country</span> <span class="hljs-attr">country</span>=<span class="hljs-string">{country}</span> /&gt;</span>
    ))
    : filterByName &amp;&amp; !filterByNameResults.length
    ? "No Result Found!"
    : hatchLoading === "processing"
    ? "Fetching Data..."
    : hatchLoading === "found" &amp;&amp; hatches &amp;&amp; hatches.length
    ? hatches.map((country) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">Country</span> <span class="hljs-attr">country</span>=<span class="hljs-string">{country}</span> /&gt;</span>)
    : "No country Found! Check your Internet Connection!"}
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
</code></pre>
<h3 id="heading-how-to-test-your-search-function">How to Test Your Search Function</h3>
<p>Let's now make a search and see what we get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/ezgif.com-gif-maker.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing How to Make Frontend Search the Wrong Way</em></p>
<p>Here's the code for the <a target="_blank" href="https://github.com/EBEREGIT/search-tutorial/tree/wrong-way">wrong way to code a search function</a>.</p>
<h3 id="heading-what-is-the-problem-with-the-search-method-above">What is the problem with the search method above?</h3>
<p>You will notice that the search string must satisfy at least one of the 3 conditions that we specified for a result to be returned. </p>
<p>So how about a user who isn't sure of the spelling but knows a couple of characters contained in the country name? </p>
<p>Do you notice that the user will take more time to search certain words because the words must me typed completely to get a match?</p>
<p><strong>Think about this</strong>: ITA- should be able to return ITALY, NIG- should be able to return NIGER and NIGERIA, and so on.</p>
<p>So while our search works, these issues make it difficult to use and negatively impact the user experience. This now takes us to the right way to make this search functionality.</p>
<h2 id="heading-how-to-build-a-search-feature-the-right-way">How to Build a Search Feature the Right Way</h2>
<p>We need to create another search just below the current one. </p>
<p>Start by setting 2 initial states to hold the <strong>search string</strong> and the <strong>search results</strong> for this new search like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [searchString, setSearchString] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [searchResult, setSearchResult] = useState([]);
</code></pre>
<p>Next, make another input box just below the first one like so:</p>
<pre><code class="lang-javascript">          {<span class="hljs-comment">/* search by name the right way*/</span>}
          &lt;input
            name=<span class="hljs-string">"searchString"</span>
            value={searchString}
            placeholder=<span class="hljs-string">"Search by name (Right Way)"</span>
            onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> setSearchString(e.target.value)}
            onKeyUp={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span>
              searchCountryByName(
                e.target.value,
                hatches,
                setSearchResult
              )
            }
          /&gt;
</code></pre>
<p>Go to the <code>src/Helpers/HatchHelper.js</code> file and create the <strong><code>searchCountryByName</code></strong> function below the <strong><code>filterCountryByName</code></strong> function:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// search countries by name the right way</span>
<span class="hljs-keyword">const</span> searchCountryByName = <span class="hljs-function">(<span class="hljs-params">
  searchString,
  countries,
  setSearchResult
</span>) =&gt;</span> {

};
</code></pre>
<p>Include it in the export like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> { filterCountryByName, searchCountryByName };
</code></pre>
<p>You can now import it in the <code>src/App.js</code> file like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { filterCountryByName, searchCountryByName } <span class="hljs-keyword">from</span> <span class="hljs-string">"./Helpers/HatchHelper"</span>;
</code></pre>
<p>You should now have a second input box that doesn’t do anything just yet:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/Screenshot-2021-12-30-at-07.38.27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screen showing a second input box that doesn’t do anything just yet</em></p>
<h4 id="heading-fleshing-out-the-function">Fleshing out the function</h4>
<p>We will now build out the function to work as we desire. </p>
<p>Begin by adding the following lines of code:</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// clear search result if the search field is empty</span>
    <span class="hljs-keyword">if</span> (searchString === <span class="hljs-string">""</span>) {
      setSearchResult([]);
    }

    <span class="hljs-comment">// discontinue if there is no search yet</span>
    <span class="hljs-keyword">if</span> (searchString === <span class="hljs-literal">null</span> || searchString === <span class="hljs-string">""</span> || countries === []) <span class="hljs-keyword">return</span>;
</code></pre>
<p>Next, empty the previous search array if any like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// empty the previous search array if any</span>
  setSearchResult([]);
</code></pre>
<p>Then create a variable that will hold our search results while searching:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> results = [];
</code></pre>
<p>Create a regular expression pattern for the search string like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// create a regular expression pattern for the search string</span>
  <span class="hljs-keyword">const</span> pattern = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(searchString, <span class="hljs-string">"gi"</span>);
</code></pre>
<blockquote>
<p>In the code above, we are saying that we want to use this <strong>searchString</strong> for something. While using it, we want it to be case-insensitive and we want all possible results. You can learn more about <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp">regular expressions here</a>.</p>
</blockquote>
<p>Now loop through countries and collect each country name like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// loop through all countries</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> country <span class="hljs-keyword">of</span> countries) {
    <span class="hljs-keyword">const</span> countryName = country.countryName;

  }
</code></pre>
<p>Still in the loop, test if the regular expression pattern matches the <strong><code>countryName</code></strong> that we just collected. If it is <strong>true</strong>, then add the country details to the <strong>results</strong> array like so:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// check if the search word or character matches</span>
<span class="hljs-keyword">if</span> (pattern.test(countryName)) {
    results.push(country);
}
</code></pre>
<p>Finish by updating the search result using the following code:</p>
<pre><code class="lang-javascript">setSearchResult(results)
</code></pre>
<p>The <code>searchCountryByName</code> function now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// search countries by name the right way</span>
<span class="hljs-keyword">const</span> searchCountryByName = <span class="hljs-function">(<span class="hljs-params">
  searchString,
  countries,
  setSearchResult
</span>) =&gt;</span> {
  <span class="hljs-comment">// clear search result if the search field is empty</span>
  <span class="hljs-keyword">if</span> (searchString === <span class="hljs-string">""</span>) {
    setSearchResult([]);
  }

  <span class="hljs-comment">// discontinue if there is no search yet</span>
  <span class="hljs-keyword">if</span> (searchString === <span class="hljs-literal">null</span> || searchString === <span class="hljs-string">""</span> || countries === []) <span class="hljs-keyword">return</span>;

  <span class="hljs-comment">// empty the previous search array if any</span>
  setSearchResult([]);
  <span class="hljs-keyword">let</span> results = [];

  <span class="hljs-comment">// create a regular expression pattern for the search string</span>
  <span class="hljs-keyword">const</span> pattern = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(searchString, <span class="hljs-string">"gi"</span>);

  <span class="hljs-comment">// loop through all countries</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> country <span class="hljs-keyword">of</span> countries) {
    <span class="hljs-keyword">const</span> countryName = country.countryName;

    <span class="hljs-comment">// check if the search word or character matches</span>
    <span class="hljs-keyword">if</span> (pattern.test(countryName)) {
      results.push(country);
    }
  }

  setSearchResult(results)
};
</code></pre>
<p>Return to the <code>src/App.js</code> file and replace the main element with the following code:</p>
<pre><code class="lang-html">        <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
          {filterByNameResults &amp;&amp; filterByNameResults.length
            ? filterByNameResults.map((country) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">Country</span> <span class="hljs-attr">country</span>=<span class="hljs-string">{country}</span> /&gt;</span>
              ))
            : filterByName &amp;&amp; !filterByNameResults.length
            ? "No Result Found!"
            : searchResult &amp;&amp; searchResult.length
            ? searchResult.map((country) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">Country</span> <span class="hljs-attr">country</span>=<span class="hljs-string">{country}</span> /&gt;</span>)
            : searchString &amp;&amp; !searchResult.length
            ? "No Result Found!"
            : hatchLoading === "processing"
            ? "Fetching Data..."
            : hatchLoading === "found" &amp;&amp; hatches &amp;&amp; hatches.length
            ? hatches.map((country) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">Country</span> <span class="hljs-attr">country</span>=<span class="hljs-string">{country}</span> /&gt;</span>)
            : "No country Found! Check your Internet Connection!"}
        <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
</code></pre>
<p>Now, the results for the second search box are included above.</p>
<h3 id="heading-testing-your-search-function-the-right-way">Testing your search function (the right way)</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/ezgif.com-gif-maker--1-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing How to Make Frontend Search the Right Way</em></p>
<p>Walah! You just learned the right way to create a search on the front end. 😊</p>
<p>Here's the code for the <a target="_blank" href="https://github.com/EBEREGIT/search-tutorial/tree/right-way">right way to build a search function</a>.</p>
<h2 id="heading-how-to-optimize-your-search-functionality">How to Optimize Your Search Functionality</h2>
<p>We are actually done. So you can skip this if you are busy, but it will just take a moment if you want to improve your search function.</p>
<p>You will notice that when you make a search the wrong way and do not refresh the page, you will be stuck with the results of the wrong way. It would be better to get fresh results when the second search box is used for the right way. </p>
<p>To achieve that, we will need to clear all search results for every search being made – whether it is the <strong>Wrong</strong> or <strong>Right</strong> Way. Let's do the following:</p>
<p>In the <code>src/App.js</code>, replace the <em>onkey</em> event of the first search box with the following<em>:</em></p>
<pre><code class="lang-javascript">            onKeyUp={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span>
              filterCountryByName(
                e.target.value,
                hatches,
                setFilterByNameResults,
                setSearchString,
                setSearchResult
              )
            }
</code></pre>
<p>Replace the <em>onkey</em> event of the second search box with the following<em>:</em></p>
<pre><code class="lang-javascript">            onKeyUp={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span>
              searchCountryByName(
                e.target.value,
                hatches,
                setSearchResult,
                setFilterByName,
                setFilterByNameResults
              )
            }
</code></pre>
<p>In the <code>src/Helpers/HatchHelper.js</code> file, add the 2 parameters we just passed into the <strong><code>filterCountryByName</code></strong> like so:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// search countries by name</span>
<span class="hljs-keyword">const</span> filterCountryByName = <span class="hljs-function">(<span class="hljs-params">
  name,
  countries,
  setResults,
  setSearchString,
  setSearchResult
</span>) =&gt;</span> {...}
</code></pre>
<p>Next, just before clearing the initial search results, clear the other search field and results like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// clear the other search field and results if any</span>
  setSearchString(<span class="hljs-string">""</span>);
  setSearchResult([]);
</code></pre>
<p>Now do the same for the <strong><code>searchCountryByName</code></strong> function.</p>
<h4 id="heading-when-you-are-done-you-should-have-the-following-result">When you are done, you should have the following result:</h4>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/ezgif.com-gif-maker--2--1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Our application after we have optimised the functionality</em></p>
<p>Awesome! 👍🏾👍🏾👍🏾</p>
<p>Here's the <a target="_blank" href="https://github.com/EBEREGIT/search-tutorial/tree/optimization">optimisation code</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>It has been an awesome ride with you as we saw the mistakes many of us have made and how to correct them by creating a search function that offers the best experience to the user.</p>
<p>I believe the code can be improved even more. So I encourage to take a look at the code again and see how you can make it even better.</p>
<p>All the code is <a target="_blank" href="https://github.com/EBEREGIT/search-tutorial">here</a>. Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Search Filter using React and React Hooks ]]>
                </title>
                <description>
                    <![CDATA[ By Nishant Kumar When you send a GET request to an API, you get the response data back from the server. But sometimes managing this data can be a problem. In this blog post, I will show you how to create a search filter in React. It will search for ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-search-filter-using-react-and-react-hooks/</link>
                <guid isPermaLink="false">66d4604c7df3a1f32ee7f87b</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 17 Aug 2021 17:56:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/How-to-Build-a-Weather-Application-using-React--23-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Nishant Kumar</p>
<p>When you send a GET request to an API, you get the response data back from the server. But sometimes managing this data can be a problem.</p>
<p>In this blog post, I will show you how to create a search filter in React. It will search for a particular term in the data using functional components and React hooks. </p>
<h2 id="heading-how-to-make-a-get-request-to-an-api">How to Make a GET Request to an API</h2>
<p>First of all, let's make a GET request to an API which will fetch some data from the server. You can use any server you want to get the data, but in this article I'll use {JSON} Placeholder to fetch the users list.</p>
<p>In this example, we have cards which show the names and emails of different users. We also have a search input box which we'll use to search for a particular user.</p>
<pre><code><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { Card, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'semantic-ui-react'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Posts</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [APIData, setAPIData] = useState([])
    useEffect(<span class="hljs-function">() =&gt;</span> {
        axios.get(<span class="hljs-string">`https://jsonplaceholder.typicode.com/users`</span>)
            .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
                setAPIData(response.data);
            })
    }, [])

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">padding:</span> <span class="hljs-attr">20</span> }}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">'search'</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Search...'</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Card.Group</span> <span class="hljs-attr">itemsPerRow</span>=<span class="hljs-string">{3}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                {APIData.map((item) =&gt; {
                    return (
                        <span class="hljs-tag">&lt;<span class="hljs-name">Card</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">Card.Content</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">Card.Header</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Header</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">Card.Description</span>&gt;</span>
                                    {item.email}
                                <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Description</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Content</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
                    )
                })}
            <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
}
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screenshot-2021-08-14-202008.png" alt="Image" width="600" height="400" loading="lazy">
<em>Getting the List of Users and a Search Input at the top</em></p>
<p>And if you don't know how to handle GET API calls in React, follow my blog on <a target="_blank" href="https://www.freecodecamp.org/news/how-to-perform-crud-operations-using-react/">React CRUD Operations</a> or my video on <a target="_blank" href="https://youtu.be/-ZMP8ZladIQ">React CRUD Operations</a> where I show you how to handle API calls in React.</p>
<h2 id="heading-how-to-get-search-input-from-the-search-input-box">How to Get Search Input from the Search Input Box</h2>
<p>Now, let's get our search query from the search input box.</p>
<p>Create a state for the search input.</p>
<pre><code><span class="hljs-keyword">const</span> [searchInput, setSearchInput] = useState(<span class="hljs-string">''</span>);
</code></pre><p>Here, <code>searchInput</code> is a string, and we'll use <code>setSearchInput</code> to set the search input.</p>
<p>Now, we'll create a function that will handle our search functionality.</p>
<pre><code><span class="hljs-keyword">const</span> searchItems = <span class="hljs-function">() =&gt;</span> {

}
</code></pre><p>And bind this function to the search input via the <code>onChange</code> event.</p>
<pre><code>&lt;Input icon=<span class="hljs-string">'search'</span>
                placeholder=<span class="hljs-string">'Search...'</span>
                onChange={<span class="hljs-function">() =&gt;</span> searchItems()}
            /&gt;
</code></pre><p>So, whenever we type something in the input field, the <code>searchItems</code> will run.</p>
<p>Now, we need to pass the input value to the <code>searchItems</code> function.</p>
<pre><code>&lt;Input icon=<span class="hljs-string">'search'</span>
                placeholder=<span class="hljs-string">'Search...'</span>
                onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> searchItems(e.target.value)}
            /&gt;
</code></pre><p>Next, let's receive the search query into the function and set the <code>searchInput</code> state to this value using <code>setSearchInput</code> that we created previously.</p>
<pre><code><span class="hljs-keyword">const</span> searchItems = <span class="hljs-function">(<span class="hljs-params">searchValue</span>) =&gt;</span> {
        setSearchInput(searchValue)
    }
</code></pre><p>You can check this whether it is working on not by consoling <code>searchValue</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screenshot-2021-08-14-203750.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, I am typing my name here and it is showing up in the console.</p>
<h2 id="heading-how-to-filter-items-based-on-the-search-results">How to Filter Items Based on the Search Results</h2>
<p>Now, we are going to filter out our APIData using the filter method.</p>
<pre><code><span class="hljs-keyword">const</span> searchItems = <span class="hljs-function">(<span class="hljs-params">searchValue</span>) =&gt;</span> {
        setSearchInput(searchValue)
        APIData.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.values(item).join(<span class="hljs-string">''</span>).toLowerCase().includes(searchInput.toLowerCase())
        })
    }
</code></pre><p>In this function <code>searchTerm</code>, you can see that we are using the <code>filter</code> method to filter out APIData state, which contains the data coming from the server.</p>
<p>We are also using <code>Object.values</code> to get the values from the object item. </p>
<p>Then, we are converting the values into a string using the <code>join(' ')</code> method.</p>
<p>Next, we are changing that string values into lowercase using the <code>toLowerCase</code> method. </p>
<p>And lastly, we are checking if this string includes our search input that we typed into the search bar. We also convert it to lowercase to make sure that if we type our term in uppercase, it converts the string to lowercase to make the search more effective.</p>
<p>Then, we return the whole query.</p>
<p>Now we need to set this filtered array into a variable.</p>
<pre><code><span class="hljs-keyword">const</span> filteredData = APIData.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.values(item).join(<span class="hljs-string">''</span>).toLowerCase().includes(searchInput.toLowerCase())
})
</code></pre><p>Let's check the above functionality by consoling it. So, search a user name and you will see that you get the data for that username in particular.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screenshot-2021-08-14-211709.png" alt="Image" width="600" height="400" loading="lazy">
<em>Getting the search item into the console</em></p>
<p>Now, we need a state where we can store the filtered data. So, let's create one.</p>
<pre><code><span class="hljs-keyword">const</span> [filteredResults, setFilteredResults] = useState([]);
</code></pre><p>Create one state that will contain our filtered data.</p>
<p>Then set this state to <code>filteredData</code> in the <code>searchItems</code> function using <code>setFilteredResults</code>.</p>
<pre><code><span class="hljs-keyword">const</span> searchItems = <span class="hljs-function">(<span class="hljs-params">searchValue</span>) =&gt;</span> {
        setSearchInput(searchValue)
        <span class="hljs-keyword">const</span> filteredData = APIData.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.values(item).join(<span class="hljs-string">''</span>).toLowerCase().includes(searchInput.toLowerCase())
        })
        setFilteredResults(filteredData)
    }
</code></pre><h2 id="heading-how-to-show-the-filtered-results-in-the-user-interface">How to Show the Filtered Results in the User Interface</h2>
<p>Now, let's show these filtered results in our main UI.</p>
<p>First we need to write some code that checks if our search input is empty, and if so, shows all the data. Otherwise it will filter them according to the search input.</p>
<pre><code><span class="hljs-keyword">const</span> searchItems = <span class="hljs-function">(<span class="hljs-params">searchValue</span>) =&gt;</span> {
        setSearchInput(searchValue)
        <span class="hljs-keyword">if</span> (searchInput !== <span class="hljs-string">''</span>) {
            <span class="hljs-keyword">const</span> filteredData = APIData.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.values(item).join(<span class="hljs-string">''</span>).toLowerCase().includes(searchInput.toLowerCase())
            })
            setFilteredResults(filteredData)
        }
        <span class="hljs-keyword">else</span>{
            setFilteredResults(APIData)
        }
    }
</code></pre><p>We also need this check in the return part of the application.</p>
<p>So, if the search term's length is greater than 1, we will show filtered data. Otherwise we will show all the data which is stored in the API Data state.</p>
<pre><code>&lt;Card.Group itemsPerRow={<span class="hljs-number">3</span>} style={{ <span class="hljs-attr">marginTop</span>: <span class="hljs-number">20</span> }}&gt;
                {searchInput.length &gt; <span class="hljs-number">1</span> ? (
                    filteredResults.map(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
                        <span class="hljs-keyword">return</span> (
                            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Card</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">Card.Content</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Header</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Header</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Description</span>&gt;</span>
                                        {item.email}
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Description</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Content</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span></span>
                        )
                    })
                ) : (
                    APIData.map(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
                        <span class="hljs-keyword">return</span> (
                            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Card</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">Card.Content</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Header</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Header</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Description</span>&gt;</span>
                                        {item.email}
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Description</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Content</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span></span>
                        )
                    })
                )}
            &lt;/Card.Group&gt;
</code></pre><p>Now, if we search some username in the search field, we will get that specific user's data.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screenshot-2021-08-14-212917.png" alt="Image" width="600" height="400" loading="lazy">
<em>Getting the search input's results in the UI</em></p>
<p>And if we remove the name, we will get all the data.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screenshot-2021-08-14-213037.png" alt="Image" width="600" height="400" loading="lazy">
<em>Getting all the data if the search input is empty</em></p>
<p>Here is all the code for your reference:</p>
<pre><code><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { Card, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'semantic-ui-react'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Posts</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [APIData, setAPIData] = useState([])
    <span class="hljs-keyword">const</span> [filteredResults, setFilteredResults] = useState([]);
    <span class="hljs-keyword">const</span> [searchInput, setSearchInput] = useState(<span class="hljs-string">''</span>);
    useEffect(<span class="hljs-function">() =&gt;</span> {
        axios.get(<span class="hljs-string">`https://jsonplaceholder.typicode.com/users`</span>)
            .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
                setAPIData(response.data);
            })
    }, [])

    <span class="hljs-keyword">const</span> searchItems = <span class="hljs-function">(<span class="hljs-params">searchValue</span>) =&gt;</span> {
        setSearchInput(searchValue)
        <span class="hljs-keyword">if</span> (searchInput !== <span class="hljs-string">''</span>) {
            <span class="hljs-keyword">const</span> filteredData = APIData.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.values(item).join(<span class="hljs-string">''</span>).toLowerCase().includes(searchInput.toLowerCase())
            })
            setFilteredResults(filteredData)
        }
        <span class="hljs-keyword">else</span>{
            setFilteredResults(APIData)
        }
    }

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">padding:</span> <span class="hljs-attr">20</span> }}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">'search'</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Search...'</span>
                <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> searchItems(e.target.value)}
            /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Card.Group</span> <span class="hljs-attr">itemsPerRow</span>=<span class="hljs-string">{3}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                {searchInput.length &gt; 1 ? (
                    filteredResults.map((item) =&gt; {
                        return (
                            <span class="hljs-tag">&lt;<span class="hljs-name">Card</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">Card.Content</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Header</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Header</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Description</span>&gt;</span>
                                        {item.email}
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Description</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Content</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
                        )
                    })
                ) : (
                    APIData.map((item) =&gt; {
                        return (
                            <span class="hljs-tag">&lt;<span class="hljs-name">Card</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">Card.Content</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Header</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Header</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">Card.Description</span>&gt;</span>
                                        {item.email}
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Description</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Content</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
                        )
                    })
                )}
            <span class="hljs-tag">&lt;/<span class="hljs-name">Card.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
}
</code></pre><p>Now there you have it, a fully functional search filter in React using React hooks.</p>
<p>We often handle this functionality from the back end side by passing search query parameters in the API endpoint. But it's important to know how to handle it from the front end side too.</p>
<p>You can also check my YouTube video on <a target="_blank" href="https://youtu.be/8YsQmvJ9UZE">Building a Search Filter using React and React Hooks</a> if you'd like to supplement this article.</p>
<blockquote>
<p>That's all folks. Happy Learning.</p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
