Soroush Neyestani

Software Engineer

Application Architect

Enterprise Application Developer

Technical Author & Educator

Custom Boolean Query Parser & Set-Based Search Engine

Laravel · Livewire · Nested Boolean Expressions · Multi-Source Search · AND / OR / NOT

Application-Level Search Architecture Built Under Elasticsearch Deployment Constraints

Project positioning

This project was developed as an advanced search subsystem in Laravel when the project constraints did not allow deployment of Elasticsearch in the target environment.

Rather than reducing the requirement to a simple SQL LIKE search, the implementation introduced a custom Boolean query interpreter capable of:

  • searching across multiple semantic data sources,
  • evaluating independent search blocks,
  • combining result sets with AND, OR, and NOT,
  • supporting grouped / nested Boolean expressions,
  • normalizing heterogeneous data sources into a common result-ID space,
  • and returning the final result set through Laravel / Livewire with pagination.

The strongest portfolio framing is:

A custom application-level Boolean search engine implemented in Laravel/Livewire, with multi-source query resolution, nested Boolean expressions, and set-based result evaluation.

It should not be described merely as:

“an advanced search form.”

The important engineering work was the query interpretation and evaluation layer behind the interface.


Classification

  • Project Type: Search Engine / Query Interpreter
  • Framework: Laravel
  • Reactive UI: Livewire
  • Primary Problem: Advanced multi-source search without Elasticsearch
  • Query Model: Nested Boolean expressions
  • Supported Operators: AND, OR, NOT
  • Evaluation Model: Set algebra over normalized result IDs
  • Data Sources visible in the historical implementation:
    • All Data
    • Authors
    • Highlights
    • Keywords
    • Learning Point
  • Pagination: Livewire pagination
  • Deployment Constraint: Elasticsearch not available for online deployment due to employer/customer constraints around data protection/infrastructure/budget
  • Portfolio Relevance: Very High
  • Suggested CV Relevance: Tier A — Algorithms, Search, Query Parsing, Laravel, Livewire, Relational Data Modeling

Website Card

Title:
Custom Boolean Query Parser & Set-Based Search Engine

Subtitle:
Laravel · Livewire · Nested Expressions · Multi-Source Search

One-line Description:
Built a custom Laravel/Livewire search engine that interprets nested Boolean expressions across multiple data sources and combines normalized result sets using AND, OR, and NOT without relying on Elasticsearch.

Categories:

  • Laravel
  • Livewire
  • Search Engine
  • Query Parser
  • Boolean Logic
  • Algorithms
  • Relational Search
  • Set Algebra
  • Advanced Search

Concept Tags:
Laravel · Livewire · AND · OR · NOT · Nested Query · Query Parser · Set Intersection · Set Union · Set Difference


Executive Summary

The project required more than a normal keyword search.

Users needed to construct searches such as:

("gastric outlet obstruction" OR GOO) AND diabetes

and also build advanced multi-row queries where each row could search a different logical source such as:

Authors
Highlights
Keywords
Learning Point
All Data

Those individual query blocks could then be connected with Boolean operators:

AND
OR
NOT

The result was effectively a small search language.

Conceptually:

Search Term / Search Block
        ↓
Source Resolver
        ↓
Result ID Set
        ↓
Boolean Operator
        ↓
Combined Result Set
        ↓
Final Search Results

Why the Project Was Needed

A basic database search usually handles a pattern such as:

WHERE caption LIKE '%diabetes%'

The requirement here was substantially more complex.

Users needed to ask questions such as:

Author = Smith
AND
Keyword = Diabetes
NOT
Highlight = Surgery

or:

("gastric outlet obstruction" OR GOO)
AND
diabetes

This means the search engine needed to understand:

  • search field,
  • search term,
  • Boolean operator,
  • grouping,
  • nesting,
  • and result-set combination.

Infrastructure Constraint

The project could not depend on an online Elasticsearch deployment.

The relevant project constraint was not a lack of awareness of Elasticsearch.

Instead, the application had to operate under restrictions related to:

  • data protection,
  • customer infrastructure,
  • deployment policy,
  • and/or available project budget.

Therefore the search logic was implemented inside the Laravel application stack.

A precise portfolio description is:

A custom application-level search engine was implemented because Elasticsearch could not be deployed in the target environment.


Core Idea

The central design decision was to convert heterogeneous search results into a common ID space.

Each search source produced a set of matching prototype/result IDs.

Example:

Authors
   ↓
Matching Author Records
   ↓
Author ↔ Prototype Relation
   ↓
Prototype IDs

Similarly:

Keywords
   ↓
Matching Keyword Records
   ↓
Keyword ↔ Prototype Relation
   ↓
Prototype IDs

Once all sources returned the same kind of identifier, Boolean logic could operate on sets instead of on unrelated tables.


Normalization Layer

Conceptually:

Authors ───────────┐
Highlights ────────┤
Keywords ──────────┤
Learning Points ───┤
All Data ──────────┘
        ↓
Normalized Result IDs
        ↓
Boolean Evaluation

This normalization layer is one of the strongest parts of the design.


Search Sources

The historical screenshots and code show multiple searchable sources.

1. All Data

The implementation searches directly against the main prototype/entity table.

The screenshot shows logic conceptually equivalent to:

AllPrototype::where(
    'caption',
    'LIKE',
    '%' . $searching . '%'
)
->pluck('id')
->toArray();

This produces matching top-level record IDs directly.


2. Authors

The code searches an author-related table first:

Author Search
     ↓
Matching Author IDs
     ↓
Author-to-Prototype Relation
     ↓
Prototype IDs

The screenshot shows the use of an intermediate relation table similar to:

AuthorsPrototypes

This demonstrates that the search engine had to traverse relational data rather than only search one flat table.


3. Highlights

The same pattern appears for highlighted / important content:

Highlight Search
      ↓
Highlight IDs
      ↓
Highlight-to-Prototype Relation
      ↓
Prototype IDs

4. Keywords

Keywords are resolved through another relation:

Keyword Search
      ↓
Keyword IDs
      ↓
Keyword-to-Prototype Relation
      ↓
Prototype IDs

5. Learning Point

Learning points are also searched independently and then normalized back to the shared result entity:

Learning Point
      ↓
Learning Point IDs
      ↓
LearningPoint ↔ Prototype Relation
      ↓
Prototype IDs

Shared Result Space

After source-specific searching, every query block becomes:

Set<int> PrototypeIds

This is what makes generic Boolean evaluation possible.


Boolean Operators

The historical implementation visibly maps Boolean operators to array/set operations.

AND

The code uses:

array_intersect(...)

Mathematically:

A AND B
=
A ∩ B

Meaning:

keep only result IDs that exist in both sets.


OR

The code uses:

array_unique(array_merge(...))

Mathematically:

A OR B
=
A ∪ B

Meaning:

include result IDs that exist in either set.


NOT

The code uses:

array_diff(...)

Conceptually:

A NOT B
=
A − B

Meaning:

keep IDs from the first set except those that occur in the second.


Why Set Algebra Was a Good Fit

Once each search source was normalized to IDs, the logical problem became independent of the database schema.

The engine no longer needed to know:

"This came from Authors"

or:

"This came from Keywords"

during final Boolean combination.

It only needed:

Set A
Set B
Operator

This simplifies the logical model significantly.


Query Evaluation Model

Conceptually:

Query A
   ↓
Set A

Query B
   ↓
Set B

Operator
   ↓
A ∩ B
or
A ∪ B
or
A − B

Nested Boolean Expressions

The project supported nested search expressions.

This means a simple search could become a component inside a larger search.

Example:

Q1 = Author contains "Smith"

Q2 = Keyword contains "Diabetes"

Q3 = Highlight contains "Surgery"

First:

Q1 AND Q2

produces:

R1

Then:

R1 NOT Q3

produces:

(Author = Smith AND Keyword = Diabetes)
NOT
Highlight = Surgery

This result could then participate in another expression.


Recursive Search Concept

Conceptually:

Expression
├── Left Expression
├── Boolean Operator
└── Right Expression

This is structurally recursive.

A nested query is therefore not just a string.

It can be modeled as a tree.


Query Tree Example

Input:

(A OR B) AND C

Tree:

        AND
       /   \
     OR     C
    /  \
   A    B

Evaluation proceeds bottom-up.


Larger Example

(
    (Author = Smith OR Author = Jones)
    AND
    Keyword = Diabetes
)
NOT
Highlight = Surgery

Conceptual tree:

            NOT
           /   \
         AND   Highlight=Surgery
        /   \
      OR     Keyword=Diabetes
     /  \
Smith     Jones

UI — Simple Search

The historical UI includes a top-level free-text search.

The example placeholder visible in the screenshot demonstrates Boolean syntax:

("gastric outlet obstruction" OR GOO) AND diabetes

This immediately communicates that the search engine supports expressions rather than only literal keyword matching.


UI — Advanced Search

The advanced form contains several query rows.

Each row provides:

  • a data source selector,
  • a search term input,
  • and a Boolean operator connection.

This allows the user to compose search logic visually.


Search Field Selector

The source selector visibly contains options such as:

All Data
Authors
Highlights
Keywords
Learning Point

This means the user can decide the semantic context of each term.


Boolean Operator Selector

The operator selector visibly contains:

OR
AND
NOT

This provides explicit control over how adjacent search blocks interact.


Visual Query Builder

The advanced search screen is essentially a visual query builder.

Instead of writing:

(author:"Smith" AND keyword:"diabetes")

the user can construct the same intent through rows and selectors.

This reduces the learning curve.


Dual Interaction Model

The project therefore supported two styles:

Textual Expression

("gastric outlet obstruction" OR GOO) AND diabetes

Visual Builder

[Authors] [Smith]      AND
[Keywords] [Diabetes]  NOT
[Highlights] [Surgery]

Both represent Boolean search logic.


Livewire Component

The code screenshot shows:

class SearchAdvanced extends Component

and:

use WithPagination;

This confirms that the advanced search was implemented as a Livewire component.


Livewire Responsibilities

The component handled:

  • user search inputs,
  • source selectors,
  • operators,
  • result calculation,
  • pagination,
  • render lifecycle.

Historically, much of the query logic was also contained inside the component itself.


Historical Parser Logic

The screenshot shows the implementation inspecting the input string for operators such as:

AND
OR
NOT

It also checks whether the first character is an opening parenthesis:

(

This demonstrates that the implementation attempted to interpret expression structure rather than treat the entire string as plain text.


String Parsing

The historical implementation contains logic similar to:

Normalize Case
      ↓
Search for " AND "
      ↓
Search for " OR "
      ↓
Search for " NOT "
      ↓
Inspect Parentheses
      ↓
Split / Transform Expression

This is effectively a lightweight parser.


Query Language

The project implemented a small domain-specific search language.

Its conceptual grammar can be summarized as:

Expression
  = Term
  | "(" Expression ")"
  | Expression AND Expression
  | Expression OR Expression
  | Expression NOT Expression

The historical parser implementation was imperative rather than grammar-driven, but the behavior is close to this conceptual language.


Query Interpreter

The overall engine can be described as:

Input Expression
      ↓
Interpretation
      ↓
Source-Specific Search
      ↓
Normalized IDs
      ↓
Boolean Evaluation
      ↓
Final Records

Search Engine vs Query Builder

This project contains both:

Query Builder

The UI where users define search blocks.

Query Engine

The backend that evaluates those blocks.

These should be treated as separate architectural concerns.


Historical Implementation Evidence

The screenshots show:

  • SearchAdvanced extends Component
  • WithPagination
  • request-driven field selection
  • operator selection
  • string inspection for AND, OR, NOT
  • source-specific Eloquent queries
  • ID extraction through pluck
  • array_intersect
  • array_merge
  • array_unique
  • array_diff
  • pagination of the final result model.

This provides strong evidence that the project implemented a custom evaluator rather than only building a search UI.


Source Resolution

A clean conceptual abstraction is:

SearchSourceResolver

Input:

source = "Authors"
term = "Smith"

Output:

Set<PrototypeId>

Generic Resolver Contract

Modern V2 interface:

SearchSource
    search(string term): Set<ResultId>

Potential implementations:

AllDataSearchSource
AuthorSearchSource
HighlightSearchSource
KeywordSearchSource
LearningPointSearchSource

Boolean Evaluator

Then a separate evaluator only understands:

Set
Operator
Set

It does not care where the sets came from.

This separation improves maintainability.


Historical Coupling

In the historical component, parsing, source resolution, Boolean evaluation, and final rendering are heavily coupled.

The screenshots show many counters and large imperative branches.

This is valuable historical evidence but also clearly identifies the modernization opportunity.


Historical Complexity

The screenshot shows line numbers exceeding:

1700

inside the search implementation.

This indicates that a large amount of search behavior had accumulated in one component.

The historical system worked, but the code structure could be significantly improved.


Modern V2 Architecture

A much stronger implementation would use four main stages:

Tokenizer
   ↓
Parser
   ↓
AST
   ↓
Evaluator

with source resolution separated from expression parsing.


Full Modern Pipeline

User Input
   ↓
Tokenizer
   ↓
Parser
   ↓
Abstract Syntax Tree
   ↓
Search Source Resolver
   ↓
Set Evaluator
   ↓
Result IDs
   ↓
Repository / Query
   ↓
Pagination
   ↓
Livewire UI

Tokenizer

The tokenizer converts raw input into tokens.

Example input:

("gastric outlet obstruction" OR GOO) AND diabetes

Possible tokens:

LPAREN
PHRASE("gastric outlet obstruction")
OR
WORD(GOO)
RPAREN
AND
WORD(diabetes)

Token Types

A modern tokenizer could support:

WORD
PHRASE
LPAREN
RPAREN
AND
OR
NOT
FIELD
EOF

Parser

The parser transforms the token stream into an expression tree.

Example:

(A OR B) AND C

becomes:

AndNode
├── OrNode
│   ├── TermNode(A)
│   └── TermNode(B)
└── TermNode(C)

Abstract Syntax Tree

Example interfaces:

ExpressionNode
├── TermNode
├── AndNode
├── OrNode
└── NotNode

This makes nested expressions natural.


Evaluator

The evaluator recursively evaluates the AST.

Pseudo logic:

evaluate(TermNode)
    → source.search(term)

evaluate(AndNode)
    → intersection(left, right)

evaluate(OrNode)
    → union(left, right)

evaluate(NotNode)
    → difference(left, right)

Operator Precedence

A formal parser can define precedence explicitly.

For example:

Parentheses
NOT
AND
OR

or whatever precedence the product specification requires.

The historical implementation should only be documented with the exact behavior recoverable from source code; precedence should not be assumed.


Why AST Is Better

With an AST:

(A OR B) AND (C NOT D)

does not require special-case logic for every nesting depth.

The parser handles structure once.

The evaluator handles node types generically.


Unlimited Nesting Conceptually

The same recursive model can support:

(
    (A OR B)
    AND
    (C NOT D)
)
OR
(
    E AND
    (
        F OR G
    )
)

without multiplying if/else branches.


Parser Testing

A dedicated parser can be tested independently from the database.

Examples:

A AND B
A OR B
A NOT B
(A OR B) AND C
A AND (B OR C)

Expected ASTs can be asserted.


Search Source Testing

Each search source can be tested separately.

Example:

AuthorSearchSource("Smith")

should return the expected normalized IDs.


Evaluator Testing

The evaluator can use in-memory sets.

Example:

A = {1,2,3}
B = {2,3,4}

AND:

{2,3}

OR:

{1,2,3,4}

NOT:

{1}

This isolates the Boolean logic completely from Laravel/Eloquent.


Query Planning

A stronger V2 could optimize evaluation order.

Example:

LargeSet AND SmallSet

can often be evaluated more efficiently by resolving the more selective search first.


Cost Awareness

Potential source costs differ.

For example:

All Data LIKE search
Author relation lookup
Keyword relation lookup

may have different costs.

A future query planner could estimate selectivity.


Database-Level Optimization

The historical implementation evaluates many operations in PHP arrays.

For moderate result sets this is straightforward.

For large datasets, a modern V2 could push some Boolean operations closer to the database.

Options include:

  • subqueries,
  • joins,
  • whereExists,
  • temporary tables,
  • CTEs,
  • indexed pivot tables.

Why Application-Level Set Evaluation Still Has Value

Application-level evaluation is attractive when:

  • multiple search sources have different schemas,
  • result counts are manageable,
  • deployment simplicity matters,
  • search logic changes frequently.

It is also easier to reason about than dynamically generating deeply nested SQL.


Hybrid Strategy

A robust V2 can use:

Database
→ Resolve Individual Query Blocks

Application
→ Combine Result Sets

This preserves the original design idea while improving structure.


Result IDs vs Full Models

The historical implementation wisely works with IDs during Boolean evaluation.

This is more memory-efficient than repeatedly merging full Eloquent model objects.

Conceptually:

Search
→ IDs
→ Boolean Logic
→ Final IDs
→ Fetch Final Models

This is a good pattern.


Pagination

The final screenshot shows the final result IDs passed back to the result model and paginated.

Conceptually:

Final Result IDs
      ↓
whereIn(id, ...)
      ↓
paginate(...)

This separates logical search calculation from final record rendering.


Pagination Considerations

A modern implementation should preserve result ordering explicitly.

whereIn alone does not guarantee the original logical order.

If ranking matters, ordering must be defined separately.


Ranking

The historical evidence shows Boolean filtering, not a relevance-ranking engine.

Do not claim:

  • BM25,
  • TF-IDF,
  • relevance scoring,
  • semantic vector search,

unless implemented separately.


Search Semantics

This project is fundamentally a Boolean retrieval engine, not a ranking search engine.

That distinction is technically important.


Boolean Retrieval Model

In information retrieval terminology:

Document either matches or does not match

according to Boolean criteria.

This differs from ranked retrieval where documents receive relevance scores.


Exact Phrase Support

The example UI suggests quoted phrases such as:

"gastric outlet obstruction"

The screenshots demonstrate phrase-like syntax in the search placeholder.

The exact historical phrase-parsing behavior should be described only from verified code behavior.


Parentheses

The parser code visibly inspects parentheses.

This confirms that grouping was part of the parsing concern.

Exact nesting depth/edge-case behavior should be verified against source if needed.


Error Handling — Modern V2

A formal parser should produce useful validation errors.

Examples:

Unexpected AND
Missing closing parenthesis
Empty expression
Unknown field

Example Validation

Input:

A AND

Response:

Expected expression after AND

Query AST Serialization

A modern system could serialize visual-builder queries as JSON.

Example:

{
  "type": "AND",
  "left": {
    "type": "TERM",
    "field": "authors",
    "value": "Smith"
  },
  "right": {
    "type": "TERM",
    "field": "keywords",
    "value": "Diabetes"
  }
}

This avoids reparsing UI-generated queries from strings.


Visual Builder + Text Query Interoperability

A strong V2 could support both:

Text Query

and:

Visual Query Builder

by converting both into the same AST.


Architecture

          Text Query ───────┐
                            ↓
                        Tokenizer
                            ↓
                         Parser
                            ↓
Visual Builder ─────────→ AST
                            ↓
                      Query Evaluator
                            ↓
                    SearchSourceResolver
                            ↓
                       Result ID Set
                            ↓
                       Pagination

Field-Aware Search

Each term may contain both:

Field
Value

Example:

field = Authors
value = Smith

This is different from a global free-text search.


Domain Search Adapters

A clean V2 could define:

interface SearchAdapter
{
    public function search(string $term): array;
}

Implementations:

AuthorSearchAdapter
KeywordSearchAdapter
HighlightSearchAdapter
LearningPointSearchAdapter
AllDataSearchAdapter

Repository Layer

The search adapters should delegate database access to repositories/query objects where appropriate.

This keeps Eloquent concerns separate from expression evaluation.


Example V2 Service Graph

SearchController / Livewire Component
        ↓
SearchApplicationService
        ↓
Parser
        ↓
AST
        ↓
Evaluator
        ↓
SourceRegistry
        ↓
Search Adapters
        ↓
Repositories
        ↓
Database

Source Registry

Instead of repeated if/elseif:

if source == 1
elseif source == 2
elseif source == 3

use:

SourceRegistry

Example:

all_data       → AllDataSearchAdapter
authors        → AuthorSearchAdapter
highlights     → HighlightSearchAdapter
keywords       → KeywordSearchAdapter
learning_point → LearningPointSearchAdapter

Benefits of Source Registry

  • easier extension,
  • less branching,
  • independent testing,
  • clearer dependencies.

Adding a New Search Domain

Historical style may require editing a large branch.

V2:

Create Adapter
Register Adapter

No parser changes required.


Query Objects

Another strong option is to model each search block as:

SearchClause
├── field
├── term
└── options

and Boolean composition as expression nodes.


SQL Injection Boundary

Because the engine interprets user expressions, it must never concatenate user values into raw SQL unsafely.

The historical screenshots show Eloquent builder usage such as:

where(..., 'LIKE', ...)

which is preferable to directly concatenating raw SQL strings.


Wildcard Search

The code uses patterns similar to:

%term%

This supports substring matching.


Performance Trade-Off of %term%

Leading wildcards typically prevent normal B-tree indexes from being fully effective.

This is an important limitation of SQL-based text search.

A future implementation could use:

  • database full-text search,
  • trigram indexes,
  • PostgreSQL pg_trgm,
  • dedicated search engine if deployment constraints change.

PostgreSQL Modernization Option

If Elasticsearch remains unavailable, PostgreSQL can significantly strengthen the design.

Potential tools:

GIN indexes
pg_trgm
tsvector
tsquery

This may reduce the need for broad %LIKE% scans.


Why Elasticsearch Would Still Be Different

A dedicated search engine provides:

  • inverted indexes,
  • scoring,
  • analyzers,
  • tokenization,
  • fuzzy search,
  • scalable text retrieval.

The custom system was designed to satisfy Boolean search requirements under a constrained deployment model, not to reproduce every Elasticsearch capability.


Security / Data Protection Context

The search architecture is a good example of a technical decision shaped by deployment constraints.

A technically ideal service is not always deployable.

The engineering task becomes:

Required Functionality
+
Available Infrastructure
+
Data Constraints
=
Practical Architecture

Product Value

The project gave users advanced retrieval capability without requiring dedicated search infrastructure.

The core value was:

Multi-Domain Search
+
Nested Boolean Logic
+
Laravel-Native Deployment

Historical UI Evidence

The screenshots show:

with a Boolean-expression example.

with multiple rows.

Source selector

with:

All Data
Authors
Highlights
Keywords
Learning Point

Boolean selector

with:

AND
OR
NOT

Laravel / Livewire source code

showing the custom parser/evaluator.

This is unusually strong portfolio evidence because both UX and implementation are documented.


Suggested Screenshot Captions

Screenshot 1 — Multi-Source Query Builder

Advanced search interface allowing each search clause to target a different semantic source such as authors, highlights, keywords, learning points, or all data.

Screenshot 2 — Boolean Operators

Visual Boolean composition using AND, OR, and NOT between independent search clauses.

Screenshot 3 — Parser Logic

Historical Livewire search component parsing textual Boolean expressions and grouping syntax.

Screenshot 4 — Source Resolution

Source-specific Eloquent queries normalized into common result IDs before Boolean evaluation.

Screenshot 5 — Set-Based Evaluation

Application-layer Boolean evaluator combining result sets through difference, intersection, and union operations.


Historical vs Modern Boundary

Confirmed Historical Capabilities

  • Laravel implementation.
  • Livewire component.
  • WithPagination.
  • free-text advanced search.
  • multi-row advanced search UI.
  • source selection.
  • sources visible in screenshots:
    • All Data,
    • Authors,
    • Highlights,
    • Keywords,
    • Learning Point.
  • Boolean operators:
    • AND,
    • OR,
    • NOT.
  • inspection/parsing of textual Boolean operators.
  • parentheses-related parsing logic.
  • source-specific relational searches.
  • normalization to common result IDs.
  • array_intersect for AND.
  • array_unique(array_merge()) for OR.
  • array_diff for NOT.
  • final result filtering and pagination.
  • custom search engine used instead of Elasticsearch due to project deployment constraints.

Modern V2 Recommendations

  • tokenizer,
  • formal parser,
  • AST,
  • precedence rules,
  • source registry,
  • source adapters,
  • dedicated evaluator,
  • query validation,
  • AST serialization,
  • PostgreSQL full-text/trigram indexing,
  • parser/evaluator unit tests.

What Not to Overclaim

Do not describe the historical project as:

  • Elasticsearch replacement with equivalent performance,
  • semantic search,
  • AI search,
  • vector search,
  • full-text relevance engine,
  • BM25 search,
  • natural-language search engine,

unless those features existed separately.

The precise claim is:

Custom nested Boolean retrieval engine over relational data sources.


My Role

A strong and precise portfolio description:

I developed a custom Boolean search engine in Laravel/Livewire when Elasticsearch could not be deployed in the target environment. The system resolved queries across multiple data domains—including authors, highlights, keywords, learning points, and general content—normalized them into common result-ID sets, and evaluated nested AND/OR/NOT expressions through set operations before returning paginated results.


Engineering Highlights

  • Laravel.
  • Livewire.
  • Advanced search UI.
  • Custom Boolean expression parsing.
  • Multi-source search.
  • Relational source resolution.
  • Result normalization.
  • Set-based evaluation.
  • Nested search expressions.
  • Parentheses/grouping logic.
  • Pagination.
  • Search infrastructure implemented without Elasticsearch.
  • Application-level query interpretation.

Algorithmic Highlights

The project combines several computer-science concepts:

Parsing
+
Boolean Algebra
+
Set Theory
+
Relational Data Traversal
+
Query Evaluation

This is why it should be treated as an algorithmic project, not merely a form-heavy Laravel page.


Set Theory Mapping

AND → Intersection
OR  → Union
NOT → Difference

This mapping is one of the clearest ways to explain the engine in technical interviews.


Career Evidence

This project demonstrates experience with:

  • Search Architecture
  • Laravel
  • Livewire
  • Boolean Logic
  • Query Parsing
  • Set Algebra
  • Relational Data Modeling
  • Algorithmic Problem Solving
  • Infrastructure-Constrained Design
  • Legacy-to-Clean-Architecture Refactoring

CV Relevance

Tier A — Search / Algorithms / Backend Engineering

The strongest technical story is:

NO ELASTICSEARCH
      ↓
CUSTOM QUERY LANGUAGE
      ↓
MULTI-SOURCE RESOLUTION
      ↓
NORMALIZED RESULT SETS
      ↓
BOOLEAN SET EVALUATION
      ↓
PAGINATED SEARCH RESULTS

Interview Story

Situation

The application needed advanced search capabilities across several different kinds of data.

A dedicated Elasticsearch deployment was not available in the target environment because of project infrastructure/data-protection/budget constraints.

Task

The search experience still needed to support:

  • multiple search domains,
  • Boolean operators,
  • grouped expressions,
  • and nested combinations.

Action

I implemented the search engine inside Laravel/Livewire.

Each search clause was resolved against its specific data source.

Those heterogeneous results were normalized into a common set of top-level record IDs.

I then evaluated the Boolean logic in the application layer using set operations:

AND → intersection
OR  → union
NOT → difference

The search interface supported both free-text Boolean syntax and a visual advanced-search builder.

Result

The application gained a flexible advanced search capability without requiring a separate search infrastructure service.


Technical Interview Explanation — Short Version

“The difficult part wasn't writing LIKE queries. Each search field represented a different relational domain. I first resolved each clause into a common set of record IDs, then treated the Boolean expression as a set-algebra problem. AND became intersection, OR became union, and NOT became difference. That allowed nested search clauses to be combined independently of where each result originally came from.”


Technical Interview Explanation — Deep Version

“The historical implementation had both textual and visual Boolean search. Search clauses could target different domains, for example authors or keywords. The source-specific query first produced IDs for the main entity. Once normalized, the Boolean engine could combine these sets without caring about the original schema. The parser was implemented imperatively inside Livewire. If I rebuilt it today, I would separate tokenization, parsing, AST construction, source resolution, and evaluation so arbitrary nesting becomes recursive rather than branch-heavy.”


Suggested Website Full Description

Overview

The Custom Boolean Query Parser & Set-Based Search Engine was developed in Laravel and Livewire to provide advanced search without relying on an externally deployed Elasticsearch service.


Users could search across several semantic domains, including:

  • all data,
  • authors,
  • highlights,
  • keywords,
  • learning points.

Each domain used its own relational lookup strategy.


Result Normalization

Every search clause ultimately returned IDs belonging to the same top-level result entity.

This made search domains interoperable.


Boolean Evaluation

The normalized sets were combined using:

AND → Intersection
OR  → Union
NOT → Difference

Nested Expressions

Users could combine small expressions into larger expressions, allowing complex nested Boolean queries.


Laravel / Livewire

Livewire handled the reactive advanced-search interface and paginated result lifecycle, while the search logic was implemented as custom application-level code.


Short Website Card Copy

Custom Boolean Query Parser & Search Engine

Built a Laravel/Livewire advanced search engine that resolves multiple relational search domains into common result sets and evaluates nested AND/OR/NOT expressions through set algebra without Elasticsearch.


Alternative One-Liners

Algorithm-oriented

Built a nested Boolean search engine that converts heterogeneous relational queries into normalized ID sets and evaluates them through set intersection, union, and difference.

Laravel-oriented

Developed a Laravel/Livewire advanced search subsystem with multi-field search, nested Boolean expressions, and application-level query evaluation.

Infrastructure-oriented

Implemented advanced Boolean search directly in Laravel when deployment constraints prevented use of Elasticsearch.

Architecture-oriented

Designed a custom query interpreter separating multi-source retrieval from Boolean result-set composition.


Suggested Website Slug

/projects/laravel-boolean-search-engine

Alternative:

/projects/custom-query-parser-search

Cover Direction

Title

Custom Boolean Search Engine

Subtitle

Nested Queries · AND / OR / NOT · Multi-Source Search

Supporting Line

Laravel · Livewire · Query Parser · Set Algebra

Visual Direction

A premium square technical cover should show:

  • a central search input,
  • nested parentheses,
  • AND / OR / NOT nodes,
  • multiple data-source blocks,
  • branching query tree,
  • result-set circles/intersections,
  • Laravel / Livewire technical styling.

Primary visual story:

QUERY
→ PARSE
→ RESOLVE
→ COMBINE
→ RESULTS

Avoid making the cover look like:

  • a generic website search bar,
  • an AI chatbot,
  • an Elasticsearch dashboard.

The visual message should be:

a custom Boolean query language and evaluation engine.


Modern V2 Architecture

Livewire UI
     ↓
Search Application Service
     ↓
Tokenizer
     ↓
Parser
     ↓
AST
     ↓
Evaluator
     ↓
Search Source Registry
     ↓
Adapters
     ↓
Repositories
     ↓
Database

Suggested Modern Classes

SearchTokenizer
SearchParser
ExpressionNode
TermNode
AndNode
OrNode
NotNode
SearchEvaluator
SearchSourceRegistry
SearchSource

Example Modern PHP Domain

Conceptual:

interface ExpressionNode {}

final class TermNode implements ExpressionNode
{
    public function __construct(
        public readonly string $field,
        public readonly string $value,
    ) {}
}

final class AndNode implements ExpressionNode
{
    public function __construct(
        public readonly ExpressionNode $left,
        public readonly ExpressionNode $right,
    ) {}
}

This is illustrative V2 architecture, not historical code.


Evaluator Concept

evaluate(TermNode $node)
    => sourceRegistry
        ->for($node->field)
        ->search($node->value);

evaluate(AndNode $node)
    => intersect(
        evaluate($node->left),
        evaluate($node->right)
    );

Again, this is a modernization design.


Parser Grammar — V2

A possible grammar:

expression  := orExpr

orExpr      := andExpr ("OR" andExpr)*

andExpr     := unaryExpr ("AND" unaryExpr)*

unaryExpr   := "NOT" unaryExpr
             | primary

primary     := term
             | "(" expression ")"

If the historical semantics of NOT are binary set-difference rather than unary negation, the grammar should be adapted accordingly.


Visual Builder AST

A visual advanced-search builder can skip tokenization entirely.

It can directly construct:

AST

from UI state.

This is preferable for reliability.


Persistence of Saved Searches

A modern V2 could store AST/query definitions as JSON.

Example use cases:

  • saved searches,
  • shared searches,
  • reusable research filters.

This is a future enhancement, not a confirmed historical feature.


Query Versioning

If saved search syntax evolves, the JSON representation can include:

version

to support migrations.


Search Explain Mode

A future useful feature:

Explain Query

showing:

Author contains Smith
AND
Keyword contains Diabetes
NOT
Highlight contains Surgery

This helps users verify complex search logic.


Result Diagnostics

Another useful V2 capability:

Why did this result match?

For example:

Matched Author clause
Matched Keyword clause
Not excluded by Highlight clause

This is especially valuable in research-oriented applications.


Search Performance Telemetry

A modern system could measure:

Parse Time
Source Query Time
Set Evaluation Time
Final Fetch Time

This identifies the expensive stage.


Caching Strategy

Potential cacheable data:

  • frequently repeated source queries,
  • stable keyword mappings,
  • normalized result-ID sets.

Cache invalidation must follow domain update behavior.


Large Result Sets

PHP array operations are simple and readable but can become memory-heavy for very large sets.

V2 alternatives include:

  • database CTEs,
  • temporary result tables,
  • bitmap/set structures,
  • search-engine infrastructure if later allowed.

Why the Historical Approach Still Matters

The project demonstrates a strong engineering principle:

The lack of an ideal infrastructure component does not remove the product requirement.

Instead, the problem was reframed into:

Search Source Resolution
+
Common ID Space
+
Set Algebra

and implemented within the available stack.


Final Portfolio Statement

The project should not be introduced as:

“a Laravel advanced search form.”

Its real engineering value is the query-processing architecture behind that form.

The strongest description is:

I built a custom Boolean search engine in Laravel/Livewire that parsed complex search expressions, resolved multiple relational data sources into normalized record-ID sets, and evaluated nested AND/OR/NOT logic through set operations when Elasticsearch could not be deployed in the target environment.

Conceptually:

USER QUERY
     ↓
BOOLEAN PARSING
     ↓
MULTI-SOURCE SEARCH
     ↓
NORMALIZED ID SETS
     ↓
AND / OR / NOT
     ↓
FINAL RESULTS