/* 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);
}
}