# 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.importcollections.abcascollections_abcfromitertoolsimportchainfromtypingimportAny,Optional# 'SF' looks unused but the test suite assumes it's available# from this module so others are liable to do so as well.from..helpers.functionimportSF,ScoreFunctionfrom.utilsimportDslBasedefQ(# pylint: disable=invalid-namename_or_query:Any="match_all",**params:Any)->Any:# {"match": {"title": "python"}}ifisinstance(name_or_query,collections_abc.Mapping):ifparams:raiseValueError("Q() cannot accept parameters when passing in a dict.")iflen(name_or_query)!=1:raiseValueError('Q() can only accept dict with a single query ({"match": {...}}). '"Instead it got (%r)"%name_or_query)name,params=name_or_query.copy().popitem()# type: ignorereturnQuery.get_dsl_class(name)(_expand__to_dot=False,**params)# MatchAll()ifisinstance(name_or_query,Query):ifparams:raiseValueError("Q() cannot accept parameters when passing in a Query object.")returnname_or_query# s.query = Q('filtered', query=s.query)ifhasattr(name_or_query,"_proxied"):returnname_or_query._proxied# "match", title="python"returnQuery.get_dsl_class(name_or_query)(**params)
[docs]classQuery(DslBase):_type_name:str="query"_type_shortcut=staticmethod(Q)name:Optional[str]=Nonedef__add__(self,other:Any)->Any:# make sure we give queries that know how to combine themselves# preferenceifhasattr(other,"__radd__"):returnother.__radd__(self)returnBool(must=[self,other])def__invert__(self)->Any:returnBool(must_not=[self])def__or__(self,other:Any)->Any:# make sure we give queries that know how to combine themselves# preferenceifhasattr(other,"__ror__"):returnother.__ror__(self)returnBool(should=[self,other])def__and__(self,other:Any)->Any:# make sure we give queries that know how to combine themselves# preferenceifhasattr(other,"__rand__"):returnother.__rand__(self)returnBool(must=[self,other])
classMatchAll(Query):name="match_all"def__add__(self,other:Any)->Any:returnother._clone()__and__=__rand__=__radd__=__add__def__or__(self,other:Any)->"MatchAll":returnself__ror__=__or__def__invert__(self)->Any:returnMatchNone()EMPTY_QUERY=MatchAll()classMatchNone(Query):name="match_none"def__add__(self,other:Any)->"MatchNone":returnself__and__=__rand__=__radd__=__add__def__or__(self,other:Any)->Any:returnother._clone()__ror__=__or__def__invert__(self)->Any:returnMatchAll()classBool(Query):name="bool"_param_defs={"must":{"type":"query","multi":True},"should":{"type":"query","multi":True},"must_not":{"type":"query","multi":True},"filter":{"type":"query","multi":True},}def__add__(self,other:"Bool")->Any:q=self._clone()ifisinstance(other,Bool):q.must+=other.mustq.should+=other.shouldq.must_not+=other.must_notq.filter+=other.filterelse:q.must.append(other)returnq__radd__=__add__def__or__(self,other:"Bool")->Any:forqin(self,other):ifisinstance(q,Bool)andnotany((q.must,q.must_not,q.filter,getattr(q,"minimum_should_match",None))):other=selfifqisotherelseotherq=q._clone()ifisinstance(other,Bool)andnotany((other.must,other.must_not,other.filter,getattr(other,"minimum_should_match",None),)):q.should.extend(other.should)else:q.should.append(other)returnqreturnBool(should=[self,other])__ror__=__or__@propertydef_min_should_match(self)->Any:returngetattr(self,"minimum_should_match",0ifnotself.shouldor(self.mustorself.filter)else1,)def__invert__(self)->Any:# Because an empty Bool query is treated like# MatchAll the inverse should be MatchNoneifnotany(chain(self.must,self.filter,self.should,self.must_not)):returnMatchNone()negations=[]forqinchain(self.must,self.filter):negations.append(~q)forqinself.must_not:negations.append(q)ifself.shouldandself._min_should_match:negations.append(Bool(must_not=self.should[:]))iflen(negations)==1:returnnegations[0]returnBool(should=negations)def__and__(self,other:"Bool")->Any:q=self._clone()ifisinstance(other,Bool):q.must+=other.mustq.must_not+=other.must_notq.filter+=other.filterq.should=[]# reset minimum_should_match as it will get calculated belowif"minimum_should_match"inq._params:delq._params["minimum_should_match"]forqxin(self,other):min_should_match=qx._min_should_match# all subqueries are requiredif(isinstance(min_should_match,int)andlen(qx.should)<=min_should_match):q.must.extend(qx.should)# not all of them are required, use it and remember min_should_matchelifnotq.should:q.minimum_should_match=min_should_matchq.should=qx.should# all queries are optional, just extend shouldelifq._min_should_match==0andmin_should_match==0:q.should.extend(qx.should)# not all are required, add a should list to the must with proper min_should_matchelse:q.must.append(Bool(should=qx.should,minimum_should_match=min_should_match))else:ifnot(q.mustorq.filter)andq.should:q._params.setdefault("minimum_should_match",1)q.must.append(other)returnq__rand__=__and__classFunctionScore(Query):name="function_score"_param_defs={"query":{"type":"query"},"filter":{"type":"query"},"functions":{"type":"score_function","multi":True},}def__init__(self,**kwargs:Any)->None:if"functions"inkwargs:passelse:fns=kwargs["functions"]=[]fornameinScoreFunction._classes:ifnameinkwargs:fns.append({name:kwargs.pop(name)})super().__init__(**kwargs)# compound queriesclassBoosting(Query):name="boosting"_param_defs={"positive":{"type":"query"},"negative":{"type":"query"}}classConstantScore(Query):name="constant_score"_param_defs={"query":{"type":"query"},"filter":{"type":"query"}}classDisMax(Query):name="dis_max"_param_defs={"queries":{"type":"query","multi":True}}classFiltered(Query):name="filtered"_param_defs={"query":{"type":"query"},"filter":{"type":"query"}}classIndices(Query):name="indices"_param_defs={"query":{"type":"query"},"no_match_query":{"type":"query"}}classPercolate(Query):name="percolate"# relationship queriesclassNested(Query):name="nested"_param_defs={"query":{"type":"query"}}classHasChild(Query):name="has_child"_param_defs={"query":{"type":"query"}}classHasParent(Query):name="has_parent"_param_defs={"query":{"type":"query"}}classTopChildren(Query):name="top_children"_param_defs={"query":{"type":"query"}}# compount span queriesclassSpanFirst(Query):name="span_first"_param_defs={"match":{"type":"query"}}classSpanMulti(Query):name="span_multi"_param_defs={"match":{"type":"query"}}classSpanNear(Query):name="span_near"_param_defs={"clauses":{"type":"query","multi":True}}classSpanNot(Query):name="span_not"_param_defs={"exclude":{"type":"query"},"include":{"type":"query"}}classSpanOr(Query):name="span_or"_param_defs={"clauses":{"type":"query","multi":True}}classFieldMaskingSpan(Query):name="field_masking_span"_param_defs={"query":{"type":"query"}}classSpanContaining(Query):name="span_containing"_param_defs={"little":{"type":"query"},"big":{"type":"query"}}# Original implementation contained# a typo: remove in v8.0.SpanContainining=SpanContainingclassSpanWithin(Query):name="span_within"_param_defs={"little":{"type":"query"},"big":{"type":"query"}}# core queriesclassCommon(Query):name="common"classFuzzy(Query):name="fuzzy"classFuzzyLikeThis(Query):name="fuzzy_like_this"classFuzzyLikeThisField(Query):name="fuzzy_like_this_field"classRankFeature(Query):name="rank_feature"classDistanceFeature(Query):name="distance_feature"classGeoBoundingBox(Query):name="geo_bounding_box"classGeoDistance(Query):name="geo_distance"classGeoDistanceRange(Query):name="geo_distance_range"classGeoPolygon(Query):name="geo_polygon"classGeoShape(Query):name="geo_shape"classGeohashCell(Query):name="geohash_cell"classIds(Query):name="ids"classIntervals(Query):name="intervals"classLimit(Query):name="limit"classMatch(Query):name="match"classMatchPhrase(Query):name="match_phrase"classMatchPhrasePrefix(Query):name="match_phrase_prefix"classMatchBoolPrefix(Query):name="match_bool_prefix"classExists(Query):name="exists"classMoreLikeThis(Query):name="more_like_this"classMoreLikeThisField(Query):name="more_like_this_field"classMultiMatch(Query):name="multi_match"classPrefix(Query):name="prefix"classQueryString(Query):name="query_string"classRange(Query):name="range"classRegexp(Query):name="regexp"classShape(Query):name="shape"classSimpleQueryString(Query):name="simple_query_string"classSpanTerm(Query):name="span_term"classTemplate(Query):name="template"classTerm(Query):name="term"classTerms(Query):name="terms"classTermsSet(Query):name="terms_set"classWildcard(Query):name="wildcard"classScript(Query):name="script"classScriptScore(Query):name="script_score"_param_defs={"query":{"type":"query"}}classType(Query):name="type"classParentId(Query):name="parent_id"classWrapper(Query):name="wrapper"__all__=["SF"]