Skip to content

Commit 9aff1b7

Browse files
committed
Add fuzzy/proximity search test coverage and docs for issue #182
Closes #182 Made-with: Cursor
1 parent 574dc7f commit 9aff1b7

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

src/Foundatio.Parsers.LuceneQueries/Nodes/IQueryNode.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ public interface IFieldQueryWithProximityAndBoostNode : IFieldQueryNode
8888
/// <summary>
8989
/// The proximity/slop factor (~) for fuzzy or phrase proximity searches.
9090
/// </summary>
91+
/// <remarks>
92+
/// Non-null when the tilde (~) operator is present.
93+
/// For unquoted terms (e.g., <c>roam~0.8</c>), this indicates a fuzzy search with edit distance.
94+
/// For quoted terms (e.g., <c>"jakarta apache"~10</c>), this indicates a phrase proximity search with word slop.
95+
/// An empty string means the bare tilde was used with no explicit value (e.g., <c>term~</c>).
96+
/// </remarks>
9197
string Proximity { get; set; }
9298

9399
/// <summary>

tests/Foundatio.Parsers.LuceneQueries.Tests/QueryParserTests.cs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#define ENABLE_TRACING
1+
#define ENABLE_TRACING
22

33
using System;
44
using System.Threading.Tasks;
@@ -516,6 +516,62 @@ public async Task CanGenerateSingleQueryAsync()
516516
await new AssignOperationTypeVisitor().AcceptAsync(result, null);
517517
_logger.LogInformation("{Result}", await DebugQueryVisitor.RunAsync(result));
518518
}
519+
520+
[Theory]
521+
[InlineData("term~", null, false, "")]
522+
[InlineData("term~1", null, false, "1")]
523+
[InlineData("roam~0.8", null, false, "0.8")]
524+
[InlineData("\"phrase query\"~2", null, true, "2")]
525+
[InlineData("field:term~", "field", false, "")]
526+
[InlineData("field:\"phrase\"~3", "field", true, "3")]
527+
public void Parse_WithProximityModifier_SetsProximityOnTermNode(string query, string expectedField, bool expectedQuoted, string expectedProximity)
528+
{
529+
var parser = new LuceneQueryParser();
530+
var result = parser.Parse(query);
531+
532+
_logger.LogInformation("{Result}", DebugQueryVisitor.Run(result));
533+
string generatedQuery = GenerateQueryVisitor.Run(result);
534+
Assert.Equal(query, generatedQuery);
535+
536+
var termNode = result.Left as TermNode;
537+
Assert.NotNull(termNode);
538+
Assert.Equal(expectedField, termNode.Field);
539+
Assert.Equal(expectedQuoted, termNode.IsQuotedTerm);
540+
Assert.Equal(expectedProximity, termNode.Proximity);
541+
}
542+
543+
[Fact]
544+
public void Parse_WithFuzzyTermInGroup_SetsProximityOnInnerTermNode()
545+
{
546+
var parser = new LuceneQueryParser();
547+
var result = parser.Parse("searchKeywords:(\"Wellness\"~)");
548+
549+
_logger.LogInformation("{Result}", DebugQueryVisitor.Run(result));
550+
string generatedQuery = GenerateQueryVisitor.Run(result);
551+
Assert.Equal("searchKeywords:(\"Wellness\"~)", generatedQuery);
552+
553+
var groupNode = result.Left as GroupNode;
554+
Assert.NotNull(groupNode);
555+
Assert.Equal("searchKeywords", groupNode.Field);
556+
Assert.True(groupNode.HasParens);
557+
558+
var termNode = groupNode.Left as TermNode;
559+
Assert.NotNull(termNode);
560+
Assert.Equal("Wellness", termNode.Term);
561+
Assert.True(termNode.IsQuotedTerm);
562+
Assert.Equal("", termNode.Proximity);
563+
}
564+
565+
[Fact]
566+
public void Parse_WithoutProximityModifier_ProximityIsNull()
567+
{
568+
var parser = new LuceneQueryParser();
569+
var result = parser.Parse("field:value");
570+
571+
var termNode = result.Left as TermNode;
572+
Assert.NotNull(termNode);
573+
Assert.Null(termNode.Proximity);
574+
}
519575
}
520576

521577
public class TestQueryVisitor : ChainableQueryVisitor

tests/Foundatio.Parsers.LuceneQueries.Tests/QueryParserValidationTests.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#define ENABLE_TRACING
1+
#define ENABLE_TRACING
22

33
using System;
44
using System.Threading.Tasks;
@@ -65,6 +65,11 @@ public QueryParserValidationTests(ITestOutputHelper output) : base(output)
6565
[InlineData("roam~0.8")]
6666
[InlineData("criter^2")]
6767
[InlineData("\"blah criter\"~1")]
68+
[InlineData("field:(\"Wellness\"~)")]
69+
[InlineData("field:(\"Wellness\"~2)")]
70+
[InlineData("field:\"Wellness\"~")]
71+
[InlineData("field:Wellness~")]
72+
[InlineData("field:Wellness~2")]
6873
[InlineData("count:>1")]
6974
[InlineData(@"book.\*:test")]
7075
[InlineData("count:>=1")]

0 commit comments

Comments
 (0)