diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d6d01078a..876ec464c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### Added
- Added support for the `Cat.PitSegments` and `Cat.SegmentReplication` APIs ([#527](https://github.com/opensearch-project/opensearch-net/pull/527))
+- Added `.Strict(...)`, `.Verbatim(...)`, `.Name(...)` methods on `QueryContainer` to help modify contained query attributes ([#509](https://github.com/opensearch-project/opensearch-net/pull/509))
### Removed
- Removed the `Features` API which is not supported by OpenSearch from the low-level client ([#331](https://github.com/opensearch-project/opensearch-net/pull/331))
diff --git a/src/OpenSearch.Client/QueryDsl/Abstractions/Container/QueryContainer-Dsl.cs b/src/OpenSearch.Client/QueryDsl/Abstractions/Container/QueryContainer-Dsl.cs
index 2d4221d6e4..e7504c8591 100644
--- a/src/OpenSearch.Client/QueryDsl/Abstractions/Container/QueryContainer-Dsl.cs
+++ b/src/OpenSearch.Client/QueryDsl/Abstractions/Container/QueryContainer-Dsl.cs
@@ -131,5 +131,58 @@ out QueryContainer queryContainer
// ReSharper disable once UnusedMember.Global
internal bool ShouldSerialize(IJsonFormatterResolver formatterResolver) => IsWritable;
+
+ ///
+ /// Assigns a name to the contained query.
+ ///
+ ///
+ ///
+ public QueryContainer Name(string name)
+ {
+ ContainedQuery.Name = name;
+ return this;
+ }
+
+ ///
+ /// Applies or removes the `strict` attribute to the contained query and optionally to all child sub-queries.
+ ///
+ ///
+ /// When true, it applies the attribute to all child sub-queries.
+ ///
+ public QueryContainer Strict(bool strict = true, bool recurse = false)
+ {
+ if (recurse)
+ {
+ var visitor = new StrictnessPropagatingVisitor(strict);
+ Accept(visitor);
+ }
+ else
+ {
+ ContainedQuery.IsStrict = strict;
+ }
+
+ return this;
+ }
+
+ ///
+ /// Applies or removes the `verbatim` attribute to the contained query and optionally to all child sub-queries.
+ ///
+ ///
+ /// When true, it applies the attribute to all child sub-queries.
+ ///
+ public QueryContainer Verbatim(bool verbatim = true, bool recurse = false)
+ {
+ if (recurse)
+ {
+ var visitor = new VerbatimPropagatingVisitor(verbatim);
+ Accept(visitor);
+ }
+ else
+ {
+ ContainedQuery.IsVerbatim = verbatim;
+ }
+
+ return this;
+ }
}
}
diff --git a/src/OpenSearch.Client/QueryDsl/Visitor/StrictnessPropagatingVisitor.cs b/src/OpenSearch.Client/QueryDsl/Visitor/StrictnessPropagatingVisitor.cs
new file mode 100644
index 0000000000..c97703c6d4
--- /dev/null
+++ b/src/OpenSearch.Client/QueryDsl/Visitor/StrictnessPropagatingVisitor.cs
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+
+using System;
+
+namespace OpenSearch.Client
+{
+ public class StrictnessPropagatingVisitor : QueryVisitor
+ {
+ private readonly bool _strict;
+
+ public StrictnessPropagatingVisitor(bool strict) => _strict = strict;
+
+ public override void Visit(IQuery query)
+ {
+ query.IsStrict = _strict;
+ base.Visit(query);
+ }
+ }
+}
diff --git a/src/OpenSearch.Client/QueryDsl/Visitor/VerbatimPropagatingVisitor.cs b/src/OpenSearch.Client/QueryDsl/Visitor/VerbatimPropagatingVisitor.cs
new file mode 100644
index 0000000000..c8daa65d21
--- /dev/null
+++ b/src/OpenSearch.Client/QueryDsl/Visitor/VerbatimPropagatingVisitor.cs
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+
+namespace OpenSearch.Client
+{
+ public class VerbatimPropagatingVisitor : QueryVisitor
+ {
+ private readonly bool _verbatim;
+
+ public VerbatimPropagatingVisitor(bool verbatim) => _verbatim = verbatim;
+
+ public override void Visit(IQuery query)
+ {
+ query.IsVerbatim = _verbatim;
+ base.Visit(query);
+ }
+ }
+}
diff --git a/tests/Tests/QueryDsl/Container/QueryContainerTests.cs b/tests/Tests/QueryDsl/Container/QueryContainerTests.cs
new file mode 100644
index 0000000000..918e4afe46
--- /dev/null
+++ b/tests/Tests/QueryDsl/Container/QueryContainerTests.cs
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+
+using FluentAssertions;
+using OpenSearch.Client;
+using OpenSearch.OpenSearch.Xunit.XunitPlumbing;
+using Xunit;
+
+namespace Tests.QueryDsl.Container
+{
+ public class QueryContainerTests
+ {
+ [TU]
+ [InlineData(false, false)]
+ [InlineData(false, true)]
+ [InlineData(true, false)]
+ [InlineData(true, true)]
+ public void StrictAndVerbatimAttributesAreRecursivelySetCorrectly(bool targetStrict, bool targetVerbatim)
+ {
+ // Arrange
+ var query0 = new TermQuery { Field = "field", Value = 1, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var query1 = new BoolQuery { MustNot = new QueryContainer[] { query0 }, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var query2 = new TermQuery { Field = "field2", Value = 7, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var query3 = new BoolQuery { Must = new QueryContainer[] { query1, query2 }, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var queryContainer = new QueryContainer(query3);
+
+ // Act
+ queryContainer.Strict(targetStrict, recurse: true);
+ queryContainer.Verbatim(targetVerbatim, recurse: true);
+
+ // Assert
+ query0.IsStrict.Should().Be(targetStrict);
+ query0.IsVerbatim.Should().Be(targetVerbatim);
+ query1.IsStrict.Should().Be(targetStrict);
+ query1.IsVerbatim.Should().Be(targetVerbatim);
+ query2.IsStrict.Should().Be(targetStrict);
+ query2.IsVerbatim.Should().Be(targetVerbatim);
+ query3.IsStrict.Should().Be(targetStrict);
+ query3.IsVerbatim.Should().Be(targetVerbatim);
+ }
+
+ [TU]
+ [InlineData(false, false)]
+ [InlineData(false, true)]
+ [InlineData(true, false)]
+ [InlineData(true, true)]
+ public void StrictAndVerbatimAttributesAreSetCorrectly(bool targetStrict, bool targetVerbatim)
+ {
+ // Arrange
+ var query0 = new TermQuery { Field = "field", Value = 1, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var query1 = new BoolQuery { MustNot = new QueryContainer[] { query0 }, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var query2 = new TermQuery { Field = "field2", Value = 7, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var query3 = new BoolQuery { Must = new QueryContainer[] { query1, query2 }, IsStrict = !targetStrict, IsVerbatim = !targetVerbatim };
+ var queryContainer = new QueryContainer(query3);
+
+ // Act
+ queryContainer.Strict(targetStrict, recurse: false);
+ queryContainer.Verbatim(targetVerbatim, recurse: false);
+
+ // Assert
+ query0.IsStrict.Should().Be(!targetStrict);
+ query0.IsVerbatim.Should().Be(!targetVerbatim);
+ query1.IsStrict.Should().Be(!targetStrict);
+ query1.IsVerbatim.Should().Be(!targetVerbatim);
+ query2.IsStrict.Should().Be(!targetStrict);
+ query2.IsVerbatim.Should().Be(!targetVerbatim);
+
+ query3.IsStrict.Should().Be(targetStrict);
+ query3.IsVerbatim.Should().Be(targetVerbatim);
+ }
+
+ [TU]
+ [InlineData("name1")]
+ [InlineData("a name")]
+ [InlineData(null)]
+ public void SettingTheNameOnTheQueryContainerSetTheNameOnTheContainedQuery(string name)
+ {
+ // Arrange
+ var query0 = new TermQuery { Name = "a", Field = "field", Value = 1 };
+ var query1 = new BoolQuery { Name = "b", MustNot = new QueryContainer[] { query0 } };
+ var query2 = new TermQuery { Name = "c", Field = "field2", Value = 7 };
+ var query3 = new BoolQuery { Name = "d", Must = new QueryContainer[] { query1, query2 } };
+ var queryContainer = new QueryContainer(query3);
+
+ // Act
+ queryContainer.Name(name);
+
+ // Assert
+ query3.Name.Should().Be(name);
+ queryContainer.ContainedQuery.Name.Should().Be(name);
+ query0.Name.Should().Be("a");
+ query1.Name.Should().Be("b");
+ query2.Name.Should().Be("c");
+ }
+
+
+ }
+}