/* 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. */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. * * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch B.V. licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using OpenSearch.Net.Utf8Json; namespace OpenSearch.Client { [InterfaceDataContract] [ReadAs(typeof(BoolQuery))] public interface IBoolQuery : IQuery { /// /// The clause (query) which is to be used as a filter (in filter context). /// [DataMember(Name = "filter")] IEnumerable Filter { get; set; } [IgnoreDataMember] bool Locked { get; } /// /// Specifies a minimum number of the optional BooleanClauses which must be satisfied. /// [DataMember(Name = "minimum_should_match")] MinimumShouldMatch MinimumShouldMatch { get; set; } /// /// The clause(s) that must appear in matching documents /// [DataMember(Name = "must")] IEnumerable Must { get; set; } /// /// The clause (query) must not appear in the matching documents. /// Note that it is not possible to search on documents that only consists of a must_not clauses. /// [DataMember(Name = "must_not")] IEnumerable MustNot { get; set; } /// /// The clause (query) should appear in the matching document. A boolean query with no must clauses, one or more should clauses must match a /// document. /// The minimum number of should clauses to match can be set using . /// [DataMember(Name = "should")] IEnumerable Should { get; set; } bool ShouldSerializeShould(); bool ShouldSerializeMust(); bool ShouldSerializeMustNot(); bool ShouldSerializeFilter(); } public class BoolQuery : QueryBase, IBoolQuery { private IList _filter; private IList _must; private IList _mustNot; private IList _should; /// /// The clause (query) which is to be used as a filter (in filter context). /// public IEnumerable Filter { get => _filter; set => _filter = value.AsInstanceOrToListOrNull(); } /// /// Specifies a minimum number of the optional BooleanClauses which must be satisfied. /// public MinimumShouldMatch MinimumShouldMatch { get; set; } /// /// The clause(s) that must appear in matching documents /// public IEnumerable Must { get => _must; set => _must = value.AsInstanceOrToListOrNull(); } /// /// The clause (query) must not appear in the matching documents. Note that it is not possible to search on documents that only consists of a /// must_not clauses. /// public IEnumerable MustNot { get => _mustNot; set => _mustNot = value.AsInstanceOrToListOrNull(); } /// /// The clause (query) should appear in the matching document. A boolean query with no must clauses, one or more should clauses must match a /// document. /// The minimum number of should clauses to match can be set using . /// public IEnumerable Should { get => _should; set => _should = value.AsInstanceOrToListOrNull(); } protected override bool Conditionless => IsConditionless(this); bool IBoolQuery.Locked => Locked(this); internal static bool Locked(IBoolQuery q) => !q.Name.IsNullOrEmpty() || q.Boost.HasValue || q.MinimumShouldMatch != null; internal override void InternalWrapInContainer(IQueryContainer c) => c.Bool = this; internal static bool IsConditionless(IBoolQuery q) => q.Must.NotWritable() && q.MustNot.NotWritable() && q.Should.NotWritable() && q.Filter.NotWritable(); internal static bool ShouldSerialize(IEnumerable queries) => (queries?.Any(qq => qq != null && qq.IsWritable)).GetValueOrDefault(false); bool IBoolQuery.ShouldSerializeShould() => ShouldSerialize(Should); bool IBoolQuery.ShouldSerializeMust() => ShouldSerialize(Must); bool IBoolQuery.ShouldSerializeMustNot() => ShouldSerialize(MustNot); bool IBoolQuery.ShouldSerializeFilter() => ShouldSerialize(Filter); } public class BoolQueryDescriptor : QueryDescriptorBase, IBoolQuery> , IBoolQuery where T : class { private IList _filter; private IList _must; private IList _mustNot; private IList _should; protected override bool Conditionless => BoolQuery.IsConditionless(this); IEnumerable IBoolQuery.Filter { get => _filter; set => _filter = value.AsInstanceOrToListOrNull(); } bool IBoolQuery.Locked => BoolQuery.Locked(this); MinimumShouldMatch IBoolQuery.MinimumShouldMatch { get; set; } IEnumerable IBoolQuery.Must { get => _must; set => _must = value.AsInstanceOrToListOrNull(); } IEnumerable IBoolQuery.MustNot { get => _mustNot; set => _mustNot = value.AsInstanceOrToListOrNull(); } IEnumerable IBoolQuery.Should { get => _should; set => _should = value.AsInstanceOrToListOrNull(); } bool IBoolQuery.ShouldSerializeShould() => BoolQuery.ShouldSerialize(Self.Should); bool IBoolQuery.ShouldSerializeMust() => BoolQuery.ShouldSerialize(Self.Must); bool IBoolQuery.ShouldSerializeMustNot() => BoolQuery.ShouldSerialize(Self.MustNot); bool IBoolQuery.ShouldSerializeFilter() => BoolQuery.ShouldSerialize(Self.Filter); /// /// Specifies a minimum number of the optional BooleanClauses which must be satisfied. /// /// /// public BoolQueryDescriptor MinimumShouldMatch(MinimumShouldMatch minimumShouldMatches) => Assign(minimumShouldMatches, (a, v) => a.MinimumShouldMatch = v); /// /// The clause(s) that must appear in matching documents /// public BoolQueryDescriptor Must(params Func, QueryContainer>[] queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.Must = v); /// /// The clause(s) that must appear in matching documents /// public BoolQueryDescriptor Must(IEnumerable, QueryContainer>> queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.Must = v); /// /// The clause(s) that must appear in matching documents /// public BoolQueryDescriptor Must(params QueryContainer[] queries) => Assign(queries.ToListOrNullIfEmpty(), (a, v) => a.Must = v); /// /// The clause (query) must not appear in the matching documents. Note that it is not possible to search on documents that only consists of a /// must_not clauses. /// /// /// public BoolQueryDescriptor MustNot(params Func, QueryContainer>[] queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.MustNot = v); /// /// The clause (query) must not appear in the matching documents. Note that it is not possible to search on documents that only consists of a /// must_not clauses. /// /// /// public BoolQueryDescriptor MustNot(IEnumerable, QueryContainer>> queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.MustNot = v); /// /// The clause (query) must not appear in the matching documents. Note that it is not possible to search on documents that only consists of a /// must_not clauses. /// /// /// public BoolQueryDescriptor MustNot(params QueryContainer[] queries) => Assign(queries.ToListOrNullIfEmpty(), (a, v) => a.MustNot = v); /// /// The clause (query) should appear in the matching document. A boolean query with no must clauses, one or more should clauses must match a /// document. /// The minimum number of should clauses to match can be set using . /// /// /// public BoolQueryDescriptor Should(params Func, QueryContainer>[] queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.Should = v); /// /// The clause (query) should appear in the matching document. A boolean query with no must clauses, one or more should clauses must match a /// document. /// The minimum number of should clauses to match can be set using . /// /// /// public BoolQueryDescriptor Should(IEnumerable, QueryContainer>> queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.Should = v); /// /// The clause (query) should appear in the matching document. A boolean query with no must clauses, one or more should clauses must match a /// document. /// The minimum number of should clauses to match can be set using . /// /// /// public BoolQueryDescriptor Should(params QueryContainer[] queries) => Assign(queries.ToListOrNullIfEmpty(), (a, v) => a.Should = v); /// /// The clause (query) which is to be used as a filter (in filter context). /// /// /// public BoolQueryDescriptor Filter(params Func, QueryContainer>[] queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.Filter = v); /// /// The clause (query) which is to be used as a filter (in filter context). /// /// /// public BoolQueryDescriptor Filter(IEnumerable, QueryContainer>> queries) => Assign(queries.Select(q => q?.Invoke(new QueryContainerDescriptor())).ToListOrNullIfEmpty(), (a, v) => a.Filter = v); /// /// The clause (query) which is to be used as a filter (in filter context). /// /// /// public BoolQueryDescriptor Filter(params QueryContainer[] queries) => Assign(queries.ToListOrNullIfEmpty(), (a, v) => a.Filter = v); } }