GitHub re-engineered its Issues search to support complex nested queries and boolean operators. This involved transitioning from a flat query parser to an Abstract Syntax Tree (AST)-based approach and mapping these structures to Elasticsearch's boolean query capabilities, all while ensuring backward compatibility and maintaining performance at high QPS.
Read original on GitHub EngineeringGitHub's Issues search functionality was enhanced to move beyond simple flat queries, enabling users to construct advanced searches with logical AND/OR operators and nested parentheses. This upgrade addressed a long-standing user request for more flexible search capabilities across all issue fields.
The core architectural change involved replacing the existing IssuesQuery search module with a new ConditionalIssuesQuery module. The key innovation here was the adoption of an Abstract Syntax Tree (AST) for parsing user input. Unlike the previous flat list approach, an AST can recursively represent complex, nested query structures, which is crucial for handling boolean logic and parentheses.
class Parser < Parslet::Parser
rule(:space) { match[" "].repeat(1) }
rule(:space?) { space.maybe }
rule(:lparen) { str("(") >> space? }
rule(:rparen) { str(")") >> space? }
rule(:and_operator) { str("and") >> space? }
rule(:or_operator) { str("or") >> space? }
rule(:var) { str("var") >> match["0-9"].repeat(1).as(:var) >> space? }
# The primary rule deals with parentheses.
rule(:primary) { lparen >> or_operation >> rparen | var }
# Note that following rules are both right-recursive.
rule(:and_operation) { (primary.as(:left) >> and_operator >> and_operation.as(:right)).as(:and) | primary }
rule(:or_operation) { (and_operation.as(:left) >> or_operator >> or_operation.as(:right)).as(:or) | and_operation }
# We start at the lowest precedence rule.
root(:or_operation)
endAfter parsing, the AST is traversed recursively to generate an Elasticsearch query document. The beauty of this approach is how naturally nested AST nodes and boolean operators map to Elasticsearch's `bool` query clauses (e.g., AND to `must`, OR to `should`, NOT to `must_not`). This allows for efficient execution of complex logical searches within the underlying search engine.
System Design Lessons
When introducing significant changes to a critical system, especially one with high traffic and legacy usage, prioritize: 1. Backward Compatibility: Extensive testing and dark-shipping are crucial. 2. Performance Monitoring: Baseline new functionality and compare against existing to prevent regressions. 3. Gradual Rollout: Limit blast radius and gather feedback incrementally. 4. User Experience: Complex features should not degrade usability; thoughtful design and limitations are key.