5050import org .elasticsearch .common .bytes .BytesReference ;
5151import org .elasticsearch .common .io .stream .StreamInput ;
5252import org .elasticsearch .common .io .stream .StreamOutput ;
53+ import org .elasticsearch .common .logging .DeprecationLogger ;
54+ import org .elasticsearch .common .logging .Loggers ;
5355import org .elasticsearch .common .lucene .search .Queries ;
5456import org .elasticsearch .common .xcontent .XContent ;
5557import org .elasticsearch .common .xcontent .XContentBuilder ;
7476import org .elasticsearch .indices .breaker .NoneCircuitBreakerService ;
7577
7678import java .io .IOException ;
79+ import java .util .Collection ;
7780import java .util .Objects ;
7881
7982import static org .elasticsearch .index .mapper .SourceToParse .source ;
8285public class PercolateQueryBuilder extends AbstractQueryBuilder <PercolateQueryBuilder > {
8386 public static final String NAME = "percolate" ;
8487
88+ private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger (Loggers .getLogger (ParseField .class ));
89+
8590 static final ParseField DOCUMENT_FIELD = new ParseField ("document" );
8691 private static final ParseField QUERY_FIELD = new ParseField ("field" );
8792 private static final ParseField DOCUMENT_TYPE_FIELD = new ParseField ("document_type" );
@@ -93,6 +98,7 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder<PercolateQueryBu
9398 private static final ParseField INDEXED_DOCUMENT_FIELD_VERSION = new ParseField ("version" );
9499
95100 private final String field ;
101+ @ Deprecated
96102 private final String documentType ;
97103 private final BytesReference document ;
98104 private final XContentType documentXContentType ;
@@ -105,21 +111,30 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder<PercolateQueryBu
105111 private final Long indexedDocumentVersion ;
106112
107113 /**
108- * @deprecated use {@link #PercolateQueryBuilder(String, String, BytesReference, XContentType)} with the document content type to avoid
109- * autodetection
114+ * @deprecated use {@link #PercolateQueryBuilder(String, BytesReference, XContentType)} with the document content
115+ * type to avoid autodetection.
110116 */
111117 @ Deprecated
112118 public PercolateQueryBuilder (String field , String documentType , BytesReference document ) {
113119 this (field , documentType , document , XContentFactory .xContentType (document ));
114120 }
115121
122+ /**
123+ * Creates a percolator query builder instance for percolating a provided document.
124+ *
125+ * @param field The field that contains the percolator query
126+ * @param document The binary blob containing document to percolate
127+ * @param documentXContentType The content type of the binary blob containing the document to percolate
128+ */
129+ public PercolateQueryBuilder (String field , BytesReference document , XContentType documentXContentType ) {
130+ this (field , null , document , documentXContentType );
131+ }
132+
133+ @ Deprecated
116134 public PercolateQueryBuilder (String field , String documentType , BytesReference document , XContentType documentXContentType ) {
117135 if (field == null ) {
118136 throw new IllegalArgumentException ("[field] is a required argument" );
119137 }
120- if (documentType == null ) {
121- throw new IllegalArgumentException ("[document_type] is a required argument" );
122- }
123138 if (document == null ) {
124139 throw new IllegalArgumentException ("[document] is a required argument" );
125140 }
@@ -135,15 +150,30 @@ public PercolateQueryBuilder(String field, String documentType, BytesReference d
135150 indexedDocumentVersion = null ;
136151 }
137152
138- public PercolateQueryBuilder (String field , String documentType , String indexedDocumentIndex , String indexedDocumentType ,
139- String indexedDocumentId , String indexedDocumentRouting , String indexedDocumentPreference ,
140- Long indexedDocumentVersion ) {
153+ /**
154+ * Creates a percolator query builder instance for percolating a document in a remote index.
155+ *
156+ * @param field The field that contains the percolator query
157+ * @param indexedDocumentIndex The index containing the document to percolate
158+ * @param indexedDocumentType The type containing the document to percolate
159+ * @param indexedDocumentId The id of the document to percolate
160+ * @param indexedDocumentRouting The routing value for the document to percolate
161+ * @param indexedDocumentPreference The preference to use when fetching the document to percolate
162+ * @param indexedDocumentVersion The expected version of the document to percolate
163+ */
164+ public PercolateQueryBuilder (String field , String indexedDocumentIndex , String indexedDocumentType , String indexedDocumentId ,
165+ String indexedDocumentRouting , String indexedDocumentPreference , Long indexedDocumentVersion ) {
166+ this (field , null , indexedDocumentIndex , indexedDocumentType , indexedDocumentId , indexedDocumentRouting ,
167+ indexedDocumentPreference , indexedDocumentVersion );
168+ }
169+
170+ @ Deprecated
171+ public PercolateQueryBuilder (String field , String documentType , String indexedDocumentIndex ,
172+ String indexedDocumentType , String indexedDocumentId , String indexedDocumentRouting ,
173+ String indexedDocumentPreference , Long indexedDocumentVersion ) {
141174 if (field == null ) {
142175 throw new IllegalArgumentException ("[field] is a required argument" );
143176 }
144- if (documentType == null ) {
145- throw new IllegalArgumentException ("[document_type] is a required argument" );
146- }
147177 if (indexedDocumentIndex == null ) {
148178 throw new IllegalArgumentException ("[index] is a required argument" );
149179 }
@@ -171,7 +201,11 @@ public PercolateQueryBuilder(String field, String documentType, String indexedDo
171201 PercolateQueryBuilder (StreamInput in ) throws IOException {
172202 super (in );
173203 field = in .readString ();
174- documentType = in .readString ();
204+ if (in .getVersion ().before (Version .V_6_0_0_alpha3 )) {
205+ documentType = in .readString ();
206+ } else {
207+ documentType = in .readOptionalString ();
208+ }
175209 indexedDocumentIndex = in .readOptionalString ();
176210 indexedDocumentType = in .readOptionalString ();
177211 indexedDocumentId = in .readOptionalString ();
@@ -197,7 +231,11 @@ public PercolateQueryBuilder(String field, String documentType, String indexedDo
197231 @ Override
198232 protected void doWriteTo (StreamOutput out ) throws IOException {
199233 out .writeString (field );
200- out .writeString (documentType );
234+ if (out .getVersion ().before (Version .V_6_0_0_alpha3 )) {
235+ out .writeString (documentType );
236+ } else {
237+ out .writeOptionalString (documentType );
238+ }
201239 out .writeOptionalString (indexedDocumentIndex );
202240 out .writeOptionalString (indexedDocumentType );
203241 out .writeOptionalString (indexedDocumentId );
@@ -281,11 +319,11 @@ public static PercolateQueryBuilder fromXContent(QueryParseContext parseContext)
281319 throw new ParsingException (parser .getTokenLocation (), "[" + PercolateQueryBuilder .NAME +
282320 "] query does not support [" + token + "]" );
283321 }
284- } else if (token .isValue ()) {
322+ } else if (token .isValue () || token == XContentParser . Token . VALUE_NULL ) {
285323 if (QUERY_FIELD .match (currentFieldName )) {
286324 field = parser .text ();
287325 } else if (DOCUMENT_TYPE_FIELD .match (currentFieldName )) {
288- documentType = parser .text ();
326+ documentType = parser .textOrNull ();
289327 } else if (INDEXED_DOCUMENT_FIELD_INDEX .match (currentFieldName )) {
290328 indexedDocumentIndex = parser .text ();
291329 } else if (INDEXED_DOCUMENT_FIELD_TYPE .match (currentFieldName )) {
@@ -312,11 +350,6 @@ public static PercolateQueryBuilder fromXContent(QueryParseContext parseContext)
312350 }
313351 }
314352
315- if (documentType == null ) {
316- throw new IllegalArgumentException ("[" + PercolateQueryBuilder .NAME + "] query is missing required [" +
317- DOCUMENT_TYPE_FIELD .getPreferredName () + "] parameter" );
318- }
319-
320353 PercolateQueryBuilder queryBuilder ;
321354 if (source != null ) {
322355 queryBuilder = new PercolateQueryBuilder (field , documentType , source , XContentType .JSON );
@@ -392,11 +425,42 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
392425 throw new IllegalStateException ("no document to percolate" );
393426 }
394427
395- MapperService mapperService = context .getMapperService ();
396- DocumentMapperForType docMapperForType = mapperService .documentMapperWithAutoCreate (documentType );
397- DocumentMapper docMapper = docMapperForType .getDocumentMapper ();
428+ MappedFieldType fieldType = context .fieldMapper (field );
429+ if (fieldType == null ) {
430+ throw new QueryShardException (context , "field [" + field + "] does not exist" );
431+ }
398432
399- ParsedDocument doc = docMapper .parse (source (context .index ().getName (), documentType , "_temp_id" , document , documentXContentType ));
433+ if (!(fieldType instanceof PercolatorFieldMapper .FieldType )) {
434+ throw new QueryShardException (context , "expected field [" + field +
435+ "] to be of type [percolator], but is of type [" + fieldType .typeName () + "]" );
436+ }
437+
438+ final ParsedDocument doc ;
439+ final DocumentMapper docMapper ;
440+ final MapperService mapperService = context .getMapperService ();
441+ if (context .getIndexSettings ().isSingleType ()) {
442+ Collection <String > types = mapperService .types ();
443+ if (types .size () != 1 ) {
444+ throw new IllegalStateException ("Only a single type should exist, but [" + types .size () + " types exists" );
445+ }
446+ String type = types .iterator ().next ();
447+ if (documentType != null ) {
448+ DEPRECATION_LOGGER .deprecated ("[document_type] parameter has been deprecated because types have been deprecated" );
449+ if (documentType .equals (type ) == false ) {
450+ throw new IllegalArgumentException ("specified document_type [" + documentType +
451+ "] is not equal to the actual type [" + type + "]" );
452+ }
453+ }
454+ docMapper = mapperService .documentMapper (type );
455+ doc = docMapper .parse (source (context .index ().getName (), type , "_temp_id" , document , documentXContentType ));
456+ } else {
457+ if (documentType == null ) {
458+ throw new IllegalArgumentException ("[percolate] query is missing required [document_type] parameter" );
459+ }
460+ DocumentMapperForType docMapperForType = mapperService .documentMapperWithAutoCreate (documentType );
461+ docMapper = docMapperForType .getDocumentMapper ();
462+ doc = docMapper .parse (source (context .index ().getName (), documentType , "_temp_id" , document , documentXContentType ));
463+ }
400464
401465 FieldNameAnalyzer fieldNameAnalyzer = (FieldNameAnalyzer ) docMapper .mappers ().indexAnalyzer ();
402466 // Need to this custom impl because FieldNameAnalyzer is strict and the percolator sometimes isn't when
@@ -425,18 +489,10 @@ protected Analyzer getWrappedAnalyzer(String fieldName) {
425489 boolean mapUnmappedFieldsAsString = context .getIndexSettings ()
426490 .getValue (PercolatorFieldMapper .INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING );
427491 QueryShardContext percolateShardContext = wrap (context );
428- MappedFieldType fieldType = context .fieldMapper (field );
429- if (fieldType == null ) {
430- throw new QueryShardException (context , "field [" + field + "] does not exist" );
431- }
432492
433- if (!(fieldType instanceof PercolatorFieldMapper .FieldType )) {
434- throw new QueryShardException (context , "expected field [" + field +
435- "] to be of type [percolator], but is of type [" + fieldType .typeName () + "]" );
436- }
437493 PercolatorFieldMapper .FieldType pft = (PercolatorFieldMapper .FieldType ) fieldType ;
438494 PercolateQuery .QueryStore queryStore = createStore (pft , percolateShardContext , mapUnmappedFieldsAsString );
439- return pft .percolateQuery (documentType , queryStore , document , docSearcher );
495+ return pft .percolateQuery (queryStore , document , docSearcher );
440496 }
441497
442498 public String getField () {
0 commit comments