diff --git a/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs b/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs index bc9f61174..df30aafd9 100644 --- a/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs +++ b/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs @@ -674,5 +674,75 @@ namespace Orchard.Tests.Modules.Indexing { Assert.That(speak.Or(michael).Count(), Is.EqualTo(4)); Assert.That(speak.Xor(michael).Count(), Is.EqualTo(3)); } + + [Test] + public void ShouldAcceptNoMin() { + _provider.CreateIndex("default"); + _provider.Store("default", _provider.New(1).Add("string", "foo")); + _provider.Store("default", _provider.New(2).Add("date", new DateTime(2010, 05, 28, 12, 30, 30))); + _provider.Store("default", _provider.New(3).Add("number", 123.456)); + _provider.Store("default", _provider.New(4).Add("integer", 123)); + + Assert.That(SearchBuilder.WithinRange("string", null, "foobar").Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("date", null, new DateTime(2010, 05, 29, 12, 30, 30)).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("number", null, 123.4567).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("integer", null, 124).Count(), Is.EqualTo(1)); + } + + [Test] + public void ShouldAcceptNoMax() { + _provider.CreateIndex("default"); + _provider.Store("default", _provider.New(1).Add("string", "foo")); + _provider.Store("default", _provider.New(2).Add("date", new DateTime(2010, 05, 28, 12, 30, 30))); + _provider.Store("default", _provider.New(3).Add("number", 123.456)); + _provider.Store("default", _provider.New(4).Add("integer", 123)); + + Assert.That(SearchBuilder.WithinRange("string", "fo", null).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("date", new DateTime(2010, 05, 27, 12, 30, 30), null).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("number", 123.45, null).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("integer", 122, null).Count(), Is.EqualTo(1)); + } + + [Test] + public void ShouldIncludeBoudaries() { + _provider.CreateIndex("default"); + _provider.Store("default", _provider.New(1).Add("string", "foo")); + _provider.Store("default", _provider.New(2).Add("date", new DateTime(2010, 05, 28, 12, 30, 30))); + _provider.Store("default", _provider.New(3).Add("number", 123.456)); + _provider.Store("default", _provider.New(4).Add("integer", 123)); + + Assert.That(SearchBuilder.WithinRange("string", "foo", null).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("date", new DateTime(2010, 05, 28, 12, 30, 30), null).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("number", 123.456, null).Count(), Is.EqualTo(1)); + Assert.That(SearchBuilder.WithinRange("integer", 123, null).Count(), Is.EqualTo(1)); + } + + [Test] + public void ShouldNotIncludeLowerBoudary() { + _provider.CreateIndex("default"); + _provider.Store("default", _provider.New(1).Add("string", "foo")); + _provider.Store("default", _provider.New(2).Add("date", new DateTime(2010, 05, 28, 12, 30, 30))); + _provider.Store("default", _provider.New(3).Add("number", 123.456)); + _provider.Store("default", _provider.New(4).Add("integer", 123)); + + Assert.That(SearchBuilder.WithinRange("string", "foo", null, false).Count(), Is.EqualTo(0)); + Assert.That(SearchBuilder.WithinRange("date", new DateTime(2010, 05, 28, 12, 30, 30), null, false).Count(), Is.EqualTo(0)); + Assert.That(SearchBuilder.WithinRange("number", 123.456, null, false).Count(), Is.EqualTo(0)); + Assert.That(SearchBuilder.WithinRange("integer", 123, null, false).Count(), Is.EqualTo(0)); + } + + [Test] + public void ShouldNotIncludeUpperBoudary() { + _provider.CreateIndex("default"); + _provider.Store("default", _provider.New(1).Add("string", "foo")); + _provider.Store("default", _provider.New(2).Add("date", new DateTime(2010, 05, 28, 12, 30, 30))); + _provider.Store("default", _provider.New(3).Add("number", 123.456)); + _provider.Store("default", _provider.New(4).Add("integer", 123)); + + Assert.That(SearchBuilder.WithinRange("string", null, "foo", true, false).Count(), Is.EqualTo(0)); + Assert.That(SearchBuilder.WithinRange("date", null, new DateTime(2010, 05, 28, 12, 30, 30), true, false).Count(), Is.EqualTo(0)); + Assert.That(SearchBuilder.WithinRange("number", null, 123.456, true, false).Count(), Is.EqualTo(0)); + Assert.That(SearchBuilder.WithinRange("integer", null, 123, true, false).Count(), Is.EqualTo(0)); + } } } diff --git a/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs b/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs index e6f3dd5b2..c2f23e68f 100644 --- a/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs +++ b/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs @@ -84,9 +84,9 @@ namespace Lucene.Services { return this; } - public ISearchBuilder WithinRange(string field, int min, int max) { + public ISearchBuilder WithinRange(string field, int? min, int? max, bool includeMin = true, bool includeMax = true) { CreatePendingClause(); - _query = NumericRangeQuery.NewIntRange(field, min, max, true, true); + _query = NumericRangeQuery.NewIntRange(field, min, max, includeMin, includeMax); return this; } @@ -96,9 +96,9 @@ namespace Lucene.Services { return this; } - public ISearchBuilder WithinRange(string field, double min, double max) { + public ISearchBuilder WithinRange(string field, double? min, double? max, bool includeMin = true, bool includeMax = true) { CreatePendingClause(); - _query = NumericRangeQuery.NewDoubleRange(field, min, max, true, true); + _query = NumericRangeQuery.NewDoubleRange(field, min, max, includeMin, includeMax); return this; } @@ -112,15 +112,15 @@ namespace Lucene.Services { return this; } - public ISearchBuilder WithinRange(string field, DateTime min, DateTime max) { + public ISearchBuilder WithinRange(string field, DateTime? min, DateTime? max, bool includeMin = true, bool includeMax = true) { CreatePendingClause(); - _query = new TermRangeQuery(field, DateTools.DateToString(min, DateTools.Resolution.MILLISECOND), DateTools.DateToString(max, DateTools.Resolution.MILLISECOND), true, true); + _query = new TermRangeQuery(field, min.HasValue ? DateTools.DateToString(min.Value, DateTools.Resolution.MILLISECOND) : null, max.HasValue ? DateTools.DateToString(max.Value, DateTools.Resolution.MILLISECOND) : null, includeMin, includeMax); return this; } - public ISearchBuilder WithinRange(string field, string min, string max) { + public ISearchBuilder WithinRange(string field, string min, string max, bool includeMin = true, bool includeMax = true) { CreatePendingClause(); - _query = new TermRangeQuery(field, QueryParser.Escape(min.ToLower()), QueryParser.Escape(max.ToLower()), true, true); + _query = new TermRangeQuery(field, min != null ? QueryParser.Escape(min.ToLower()) : null, max != null ? QueryParser.Escape(max.ToLower()) : null, includeMin, includeMax); return this; } diff --git a/src/Orchard/Indexing/ISearchBuilder.cs b/src/Orchard/Indexing/ISearchBuilder.cs index de372a7eb..0c5a9df9a 100644 --- a/src/Orchard/Indexing/ISearchBuilder.cs +++ b/src/Orchard/Indexing/ISearchBuilder.cs @@ -11,10 +11,10 @@ namespace Orchard.Indexing { ISearchBuilder WithField(string field, string value); ISearchBuilder WithField(string field, int value); ISearchBuilder WithField(string field, double value); - ISearchBuilder WithinRange(string field, int min, int max); - ISearchBuilder WithinRange(string field, double min, double max); - ISearchBuilder WithinRange(string field, DateTime min, DateTime max); - ISearchBuilder WithinRange(string field, string min, string max); + ISearchBuilder WithinRange(string field, int? min, int? max, bool includeMin = true, bool includeMax = true); + ISearchBuilder WithinRange(string field, double? min, double? max, bool includeMin = true, bool includeMax = true); + ISearchBuilder WithinRange(string field, DateTime? min, DateTime? max, bool includeMin = true, bool includeMax = true); + ISearchBuilder WithinRange(string field, string min, string max, bool includeMin = true, bool includeMax = true); /// /// Mark a clause as a mandatory match. By default all clauses are optional. diff --git a/src/Orchard/Indexing/NullSearchBuilder.cs b/src/Orchard/Indexing/NullSearchBuilder.cs index 003510ad7..f46f4da30 100644 --- a/src/Orchard/Indexing/NullSearchBuilder.cs +++ b/src/Orchard/Indexing/NullSearchBuilder.cs @@ -32,19 +32,19 @@ namespace Orchard.Indexing { return this; } - public ISearchBuilder WithinRange(string field, int min, int max) { + public ISearchBuilder WithinRange(string field, int? min, int? max, bool includeMin = true, bool includeMax = true) { return this; } - public ISearchBuilder WithinRange(string field, double min, double max) { + public ISearchBuilder WithinRange(string field, double? min, double? max, bool includeMin = true, bool includeMax = true) { return this; } - public ISearchBuilder WithinRange(string field, DateTime min, DateTime max) { + public ISearchBuilder WithinRange(string field, DateTime? min, DateTime? max, bool includeMin = true, bool includeMax = true) { return this; } - public ISearchBuilder WithinRange(string field, string min, string max) { + public ISearchBuilder WithinRange(string field, string min, string max, bool includeMin = true, bool includeMax = true) { return this; }