diff --git a/src/Nest/QueryDsl/Span/Term/SpanTermQuery.cs b/src/Nest/QueryDsl/Span/Term/SpanTermQuery.cs index c8f69f799a1..642a169b3b2 100644 --- a/src/Nest/QueryDsl/Span/Term/SpanTermQuery.cs +++ b/src/Nest/QueryDsl/Span/Term/SpanTermQuery.cs @@ -9,18 +9,33 @@ namespace Nest { [InterfaceDataContract] [JsonFormatter(typeof(FieldNameQueryFormatter))] - public interface ISpanTermQuery : ITermQuery, ISpanSubQuery { } + public interface ISpanTermQuery : ISpanSubQuery, IFieldNameQuery + { + [DataMember(Name = "value")] + [JsonFormatter(typeof(SourceWriteFormatter))] + object Value { get; set; } + } [DataContract] public class SpanTermQuery : FieldNameQueryBase, ISpanTermQuery { public object Value { get; set; } - - protected override bool Conditionless => TermQuery.IsConditionless(this); + + protected override bool Conditionless => IsConditionless(this); internal override void InternalWrapInContainer(IQueryContainer c) => c.SpanTerm = this; + + internal static bool IsConditionless(ISpanTermQuery q) => q.Value == null || q.Value.ToString().IsNullOrEmpty() || q.Field.IsConditionless(); } - public class SpanTermQueryDescriptor : TermQueryDescriptorBase, ISpanTermQuery, T>, ISpanTermQuery - where T : class { } + public class SpanTermQueryDescriptor : FieldNameQueryDescriptorBase, ISpanTermQuery, T>, ISpanTermQuery + where T : class + { + protected override bool Conditionless => SpanTermQuery.IsConditionless(this); + + object ISpanTermQuery.Value { get; set; } + + public SpanTermQueryDescriptor Value(object value) => + Assign(value, (a, v) => a.Value = v); + } } diff --git a/src/Nest/QueryDsl/TermLevel/Prefix/PrefixQuery.cs b/src/Nest/QueryDsl/TermLevel/Prefix/PrefixQuery.cs index 232d8d65ab2..2cb31871213 100644 --- a/src/Nest/QueryDsl/TermLevel/Prefix/PrefixQuery.cs +++ b/src/Nest/QueryDsl/TermLevel/Prefix/PrefixQuery.cs @@ -20,6 +20,7 @@ public class PrefixQuery : FieldNameQueryBase, IPrefixQuery { public MultiTermQueryRewrite Rewrite { get; set; } public object Value { get; set; } + public bool? CaseInsensitive { get; set; } protected override bool Conditionless => TermQuery.IsConditionless(this); internal override void InternalWrapInContainer(IQueryContainer c) => c.Prefix = this; diff --git a/src/Nest/QueryDsl/TermLevel/Term/TermQuery.cs b/src/Nest/QueryDsl/TermLevel/Term/TermQuery.cs index 91e9b95ae06..ca201394824 100644 --- a/src/Nest/QueryDsl/TermLevel/Term/TermQuery.cs +++ b/src/Nest/QueryDsl/TermLevel/Term/TermQuery.cs @@ -14,12 +14,17 @@ public interface ITermQuery : IFieldNameQuery [DataMember(Name = "value")] [JsonFormatter(typeof(SourceWriteFormatter))] object Value { get; set; } + + [DataMember(Name = "case_insensitive")] + bool? CaseInsensitive { get; set; } } [DataContract] public class TermQuery : FieldNameQueryBase, ITermQuery { public object Value { get; set; } + + public bool? CaseInsensitive { get; set; } protected override bool Conditionless => IsConditionless(this); @@ -37,12 +42,19 @@ public abstract class TermQueryDescriptorBase { protected override bool Conditionless => TermQuery.IsConditionless(this); object ITermQuery.Value { get; set; } + bool? ITermQuery.CaseInsensitive { get; set; } public TDescriptor Value(object value) { Self.Value = value; return (TDescriptor)this; } + + public TDescriptor CaseInsensitive(bool? caseInsensitive = true) + { + Self.CaseInsensitive = caseInsensitive; + return (TDescriptor)this; + } } public class TermQueryDescriptor : TermQueryDescriptorBase, ITermQuery, T> diff --git a/src/Nest/QueryDsl/TermLevel/Wildcard/WildcardQuery.cs b/src/Nest/QueryDsl/TermLevel/Wildcard/WildcardQuery.cs index c2eb503144c..0cd76fd5981 100644 --- a/src/Nest/QueryDsl/TermLevel/Wildcard/WildcardQuery.cs +++ b/src/Nest/QueryDsl/TermLevel/Wildcard/WildcardQuery.cs @@ -27,6 +27,7 @@ public class WildcardQuery : FieldNameQueryBase, IWildcardQuery { public MultiTermQueryRewrite Rewrite { get; set; } public object Value { get; set; } + public bool? CaseInsensitive { get; set; } protected override bool Conditionless => TermQuery.IsConditionless(this); internal override void InternalWrapInContainer(IQueryContainer c) => c.Wildcard = this; diff --git a/tests/Tests/QueryDsl/TermLevel/Term/TermQueryUsageTests.cs b/tests/Tests/QueryDsl/TermLevel/Term/TermQueryUsageTests.cs index 0fb7b16df72..afe5a2a3149 100644 --- a/tests/Tests/QueryDsl/TermLevel/Term/TermQueryUsageTests.cs +++ b/tests/Tests/QueryDsl/TermLevel/Term/TermQueryUsageTests.cs @@ -104,4 +104,61 @@ protected override QueryContainer QueryFluent(QueryContainerDescriptor .Value(string.Empty) ); } + + //hide + [SkipVersion("<7.10.0", "Case insensitive flag added in 7.10.0")] + public class TermQueryWithCaseInsensitiveUsageTests : QueryDslUsageTestsBase + { + public TermQueryWithCaseInsensitiveUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override ConditionlessWhen ConditionlessWhen => new ConditionlessWhen(q => q.Term) + { + q => q.Field = null, + q => q.Value = " ", + q => q.Value = null + }; + + protected override QueryContainer QueryInitializer => new TermQuery + { + Name = "named_query", + Boost = 1.1, + Field = "description", + Value = "project description", + CaseInsensitive = true + }; + + protected override object QueryJson => new + { + term = new + { + description = new + { + _name = "named_query", + boost = 1.1, + value = "project description", + case_insensitive = true + } + } + }; + + protected override QueryContainer QueryFluent(QueryContainerDescriptor q) => q + .Term(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Value("project description") + .CaseInsensitive(true) + ); + + //hide + [U] + public void DeserializeShortForm() + { + using var stream = new MemoryStream(ShortFormQuery); + var query = Client.RequestResponseSerializer.Deserialize(stream); + query.Should().NotBeNull(); + query.Field.Should().Be(new Field("description")); + query.Value.Should().Be("project description"); + } + } }