parent
b55b65cd65
commit
75cedca0da
|
@ -134,8 +134,6 @@ import org.elasticsearch.action.bulk.TransportBulkAction;
|
|||
import org.elasticsearch.action.bulk.TransportShardBulkAction;
|
||||
import org.elasticsearch.action.delete.DeleteAction;
|
||||
import org.elasticsearch.action.delete.TransportDeleteAction;
|
||||
import org.elasticsearch.action.exists.ExistsAction;
|
||||
import org.elasticsearch.action.exists.TransportExistsAction;
|
||||
import org.elasticsearch.action.explain.ExplainAction;
|
||||
import org.elasticsearch.action.explain.TransportExplainAction;
|
||||
import org.elasticsearch.action.fieldstats.FieldStatsAction;
|
||||
|
@ -314,7 +312,6 @@ public class ActionModule extends AbstractModule {
|
|||
registerAction(MultiTermVectorsAction.INSTANCE, TransportMultiTermVectorsAction.class,
|
||||
TransportShardMultiTermsVectorAction.class);
|
||||
registerAction(DeleteAction.INSTANCE, TransportDeleteAction.class);
|
||||
registerAction(ExistsAction.INSTANCE, TransportExistsAction.class);
|
||||
registerAction(SuggestAction.INSTANCE, TransportSuggestAction.class);
|
||||
registerAction(UpdateAction.INSTANCE, TransportUpdateAction.class);
|
||||
registerAction(MultiGetAction.INSTANCE, TransportMultiGetAction.class,
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
|
||||
public class ExistsAction extends Action<ExistsRequest, ExistsResponse, ExistsRequestBuilder> {
|
||||
|
||||
public static final ExistsAction INSTANCE = new ExistsAction();
|
||||
public static final String NAME = "indices:data/read/exists";
|
||||
|
||||
private ExistsAction() {
|
||||
super(NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExistsResponse newResponse() {
|
||||
return new ExistsResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExistsRequestBuilder newRequestBuilder(ElasticsearchClient client) {
|
||||
return new ExistsRequestBuilder(client, this);
|
||||
}
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
import org.elasticsearch.ElasticsearchGenerationException;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.QuerySourceBuilder;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastRequest;
|
||||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExistsRequest extends BroadcastRequest<ExistsRequest> {
|
||||
|
||||
public static final float DEFAULT_MIN_SCORE = -1f;
|
||||
private float minScore = DEFAULT_MIN_SCORE;
|
||||
|
||||
@Nullable
|
||||
protected String routing;
|
||||
|
||||
@Nullable
|
||||
private String preference;
|
||||
|
||||
private BytesReference source;
|
||||
|
||||
private String[] types = Strings.EMPTY_ARRAY;
|
||||
|
||||
long nowInMillis;
|
||||
|
||||
public ExistsRequest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exists request against the provided indices. No indices provided means it will
|
||||
* run against all indices.
|
||||
*/
|
||||
public ExistsRequest(String... indices) {
|
||||
super(indices);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
ActionRequestValidationException validationException = super.validate();
|
||||
return validationException;
|
||||
}
|
||||
|
||||
/**
|
||||
* The minimum score of the documents to include in the count.
|
||||
*/
|
||||
public float minScore() {
|
||||
return minScore;
|
||||
}
|
||||
|
||||
/**
|
||||
* The minimum score of the documents to include in the count. Defaults to <tt>-1</tt> which means all
|
||||
* documents will be considered.
|
||||
*/
|
||||
public ExistsRequest minScore(float minScore) {
|
||||
this.minScore = minScore;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A comma separated list of routing values to control the shards the search will be executed on.
|
||||
*/
|
||||
public String routing() {
|
||||
return this.routing;
|
||||
}
|
||||
|
||||
/**
|
||||
* A comma separated list of routing values to control the shards the search will be executed on.
|
||||
*/
|
||||
public ExistsRequest routing(String routing) {
|
||||
this.routing = routing;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The routing values to control the shards that the search will be executed on.
|
||||
*/
|
||||
public ExistsRequest routing(String... routings) {
|
||||
this.routing = Strings.arrayToCommaDelimitedString(routings);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing preference for executing the search on shards
|
||||
*/
|
||||
public ExistsRequest preference(String preference) {
|
||||
this.preference = preference;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String preference() {
|
||||
return this.preference;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute.
|
||||
*/
|
||||
public BytesReference source() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute.
|
||||
*/
|
||||
public ExistsRequest source(QuerySourceBuilder sourceBuilder) {
|
||||
this.source = sourceBuilder.buildAsBytes(Requests.CONTENT_TYPE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute in the form of a map.
|
||||
*/
|
||||
public ExistsRequest source(Map querySource) {
|
||||
try {
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(Requests.CONTENT_TYPE);
|
||||
builder.map(querySource);
|
||||
return source(builder);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchGenerationException("Failed to generate [" + querySource + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ExistsRequest source(XContentBuilder builder) {
|
||||
this.source = builder.bytes();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute. It is preferable to use either {@link #source(byte[])}
|
||||
* or {@link #source(QuerySourceBuilder)}.
|
||||
*/
|
||||
public ExistsRequest source(String querySource) {
|
||||
this.source = new BytesArray(querySource);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute.
|
||||
*/
|
||||
public ExistsRequest source(byte[] querySource) {
|
||||
return source(querySource, 0, querySource.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute.
|
||||
*/
|
||||
public ExistsRequest source(byte[] querySource, int offset, int length) {
|
||||
return source(new BytesArray(querySource, offset, length));
|
||||
}
|
||||
|
||||
public ExistsRequest source(BytesReference querySource) {
|
||||
this.source = querySource;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of documents the query will run against. Defaults to all types.
|
||||
*/
|
||||
public String[] types() {
|
||||
return this.types;
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of documents the query will run against. Defaults to all types.
|
||||
*/
|
||||
public ExistsRequest types(String... types) {
|
||||
this.types = types;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
minScore = in.readFloat();
|
||||
routing = in.readOptionalString();
|
||||
preference = in.readOptionalString();
|
||||
source = in.readBytesReference();
|
||||
types = in.readStringArray();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeFloat(minScore);
|
||||
out.writeOptionalString(routing);
|
||||
out.writeOptionalString(preference);
|
||||
out.writeBytesReference(source);
|
||||
out.writeStringArray(types);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String sSource = "_na_";
|
||||
try {
|
||||
sSource = XContentHelper.convertToJson(source, false);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return "[" + Arrays.toString(indices) + "]" + Arrays.toString(types) + ", source[" + sSource + "]";
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
import org.elasticsearch.action.support.QuerySourceBuilder;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastOperationRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
|
||||
public class ExistsRequestBuilder extends BroadcastOperationRequestBuilder<ExistsRequest, ExistsResponse, ExistsRequestBuilder> {
|
||||
|
||||
private QuerySourceBuilder sourceBuilder;
|
||||
|
||||
public ExistsRequestBuilder(ElasticsearchClient client, ExistsAction action) {
|
||||
super(client, action, new ExistsRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of documents the query will run against. Defaults to all types.
|
||||
*/
|
||||
public ExistsRequestBuilder setTypes(String... types) {
|
||||
request.types(types);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A comma separated list of routing values to control the shards the search will be executed on.
|
||||
*/
|
||||
public ExistsRequestBuilder setRouting(String routing) {
|
||||
request.routing(routing);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preference to execute the search. Defaults to randomize across shards. Can be set to
|
||||
* <tt>_local</tt> to prefer local shards, <tt>_primary</tt> to execute only on primary shards,
|
||||
* _shards:x,y to operate on shards x & y, or a custom value, which guarantees that the same order
|
||||
* will be used across different requests.
|
||||
*/
|
||||
public ExistsRequestBuilder setPreference(String preference) {
|
||||
request.preference(preference);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The routing values to control the shards that the search will be executed on.
|
||||
*/
|
||||
public ExistsRequestBuilder setRouting(String... routing) {
|
||||
request.routing(routing);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to execute.
|
||||
*
|
||||
* @see org.elasticsearch.index.query.QueryBuilders
|
||||
*/
|
||||
public ExistsRequestBuilder setQuery(QueryBuilder queryBuilder) {
|
||||
sourceBuilder().setQuery(queryBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query binary to execute
|
||||
*/
|
||||
public ExistsRequestBuilder setQuery(BytesReference queryBinary) {
|
||||
sourceBuilder().setQuery(queryBinary);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source to execute.
|
||||
*/
|
||||
public ExistsRequestBuilder setSource(BytesReference source) {
|
||||
request().source(source);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to execute.
|
||||
*/
|
||||
public ExistsRequestBuilder setSource(byte[] querySource) {
|
||||
request.source(querySource);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExistsRequest beforeExecute(ExistsRequest request) {
|
||||
if (sourceBuilder != null) {
|
||||
request.source(sourceBuilder);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private QuerySourceBuilder sourceBuilder() {
|
||||
if (sourceBuilder == null) {
|
||||
sourceBuilder = new QuerySourceBuilder();
|
||||
}
|
||||
return sourceBuilder;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class ExistsResponse extends BroadcastResponse {
|
||||
|
||||
private boolean exists = false;
|
||||
|
||||
ExistsResponse() {
|
||||
|
||||
}
|
||||
|
||||
ExistsResponse(boolean exists, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) {
|
||||
super(totalShards, successfulShards, failedShards, shardFailures);
|
||||
this.exists = exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the documents matching the query provided exists
|
||||
*/
|
||||
public boolean exists() {
|
||||
return exists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
exists = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeBoolean(exists);
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ShardExistsRequest extends BroadcastShardRequest {
|
||||
|
||||
private float minScore;
|
||||
|
||||
private BytesReference querySource;
|
||||
|
||||
private String[] types = Strings.EMPTY_ARRAY;
|
||||
|
||||
private long nowInMillis;
|
||||
|
||||
@Nullable
|
||||
private String[] filteringAliases;
|
||||
|
||||
public ShardExistsRequest() {
|
||||
}
|
||||
|
||||
ShardExistsRequest(ShardId shardId, @Nullable String[] filteringAliases, ExistsRequest request) {
|
||||
super(shardId, request);
|
||||
this.minScore = request.minScore();
|
||||
this.querySource = request.source();
|
||||
this.types = request.types();
|
||||
this.filteringAliases = filteringAliases;
|
||||
this.nowInMillis = request.nowInMillis;
|
||||
}
|
||||
|
||||
public float minScore() {
|
||||
return minScore;
|
||||
}
|
||||
|
||||
public BytesReference querySource() {
|
||||
return querySource;
|
||||
}
|
||||
|
||||
public String[] types() {
|
||||
return this.types;
|
||||
}
|
||||
|
||||
public String[] filteringAliases() {
|
||||
return filteringAliases;
|
||||
}
|
||||
|
||||
public long nowInMillis() {
|
||||
return this.nowInMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
minScore = in.readFloat();
|
||||
|
||||
querySource = in.readBytesReference();
|
||||
|
||||
int typesSize = in.readVInt();
|
||||
if (typesSize > 0) {
|
||||
types = new String[typesSize];
|
||||
for (int i = 0; i < typesSize; i++) {
|
||||
types[i] = in.readString();
|
||||
}
|
||||
}
|
||||
int aliasesSize = in.readVInt();
|
||||
if (aliasesSize > 0) {
|
||||
filteringAliases = new String[aliasesSize];
|
||||
for (int i = 0; i < aliasesSize; i++) {
|
||||
filteringAliases[i] = in.readString();
|
||||
}
|
||||
}
|
||||
nowInMillis = in.readVLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeFloat(minScore);
|
||||
|
||||
out.writeBytesReference(querySource);
|
||||
|
||||
out.writeVInt(types.length);
|
||||
for (String type : types) {
|
||||
out.writeString(type);
|
||||
}
|
||||
if (filteringAliases != null) {
|
||||
out.writeVInt(filteringAliases.length);
|
||||
for (String alias : filteringAliases) {
|
||||
out.writeString(alias);
|
||||
}
|
||||
} else {
|
||||
out.writeVInt(0);
|
||||
}
|
||||
out.writeVLong(nowInMillis);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class ShardExistsResponse extends BroadcastShardResponse {
|
||||
|
||||
private boolean exists;
|
||||
|
||||
ShardExistsResponse() {
|
||||
}
|
||||
|
||||
ShardExistsResponse(ShardId shardId, boolean exists) {
|
||||
super(shardId);
|
||||
this.exists = exists;
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return this.exists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
exists = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeBoolean(exists);
|
||||
}
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.exists;
|
||||
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
|
||||
import org.elasticsearch.cache.recycler.PageCacheRecycler;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.routing.GroupShardsIterator;
|
||||
import org.elasticsearch.cluster.routing.ShardIterator;
|
||||
import org.elasticsearch.cluster.routing.ShardRouting;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.index.IndexService;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.shard.IndexShard;
|
||||
import org.elasticsearch.indices.IndicesService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.search.SearchService;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.internal.DefaultSearchContext;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.search.internal.ShardSearchLocalRequest;
|
||||
import org.elasticsearch.search.query.QueryPhaseExecutionException;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
|
||||
import static org.elasticsearch.action.exists.ExistsRequest.DEFAULT_MIN_SCORE;
|
||||
|
||||
public class TransportExistsAction extends TransportBroadcastAction<ExistsRequest, ExistsResponse, ShardExistsRequest, ShardExistsResponse> {
|
||||
|
||||
private final IndicesService indicesService;
|
||||
private final ScriptService scriptService;
|
||||
private final PageCacheRecycler pageCacheRecycler;
|
||||
private final BigArrays bigArrays;
|
||||
|
||||
@Inject
|
||||
public TransportExistsAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService,
|
||||
IndicesService indicesService, ScriptService scriptService,
|
||||
PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, ExistsAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
|
||||
ExistsRequest::new, ShardExistsRequest::new, ThreadPool.Names.SEARCH);
|
||||
this.indicesService = indicesService;
|
||||
this.scriptService = scriptService;
|
||||
this.pageCacheRecycler = pageCacheRecycler;
|
||||
this.bigArrays = bigArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(ExistsRequest request, ActionListener<ExistsResponse> listener) {
|
||||
request.nowInMillis = System.currentTimeMillis();
|
||||
new ExistsAsyncBroadcastAction(request, listener).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardExistsRequest newShardRequest(int numShards, ShardRouting shard, ExistsRequest request) {
|
||||
String[] filteringAliases = indexNameExpressionResolver.filteringAliases(clusterService.state(), shard.index(), request.indices());
|
||||
return new ShardExistsRequest(shard.shardId(), filteringAliases, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardExistsResponse newShardResponse() {
|
||||
return new ShardExistsResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GroupShardsIterator shards(ClusterState clusterState, ExistsRequest request, String[] concreteIndices) {
|
||||
Map<String, Set<String>> routingMap = indexNameExpressionResolver.resolveSearchRouting(clusterState, request.routing(), request.indices());
|
||||
return clusterService.operationRouting().searchShards(clusterState, concreteIndices, routingMap, request.preference());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClusterBlockException checkGlobalBlock(ClusterState state, ExistsRequest request) {
|
||||
return state.blocks().globalBlockedException(ClusterBlockLevel.READ);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClusterBlockException checkRequestBlock(ClusterState state, ExistsRequest countRequest, String[] concreteIndices) {
|
||||
return state.blocks().indicesBlockedException(ClusterBlockLevel.READ, concreteIndices);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExistsResponse newResponse(ExistsRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) {
|
||||
int successfulShards = 0;
|
||||
int failedShards = 0;
|
||||
boolean exists = false;
|
||||
List<ShardOperationFailedException> shardFailures = null;
|
||||
|
||||
// if docs do exist, the last response will have exists = true (since we early terminate the shard requests)
|
||||
for (int i = shardsResponses.length() - 1; i >= 0 ; i--) {
|
||||
Object shardResponse = shardsResponses.get(i);
|
||||
if (shardResponse == null) {
|
||||
// simply ignore non active shards
|
||||
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
|
||||
failedShards++;
|
||||
if (shardFailures == null) {
|
||||
shardFailures = new ArrayList<>();
|
||||
}
|
||||
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
|
||||
} else {
|
||||
successfulShards++;
|
||||
if ((exists = ((ShardExistsResponse) shardResponse).exists())) {
|
||||
successfulShards = shardsResponses.length() - failedShards;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ExistsResponse(exists, shardsResponses.length(), successfulShards, failedShards, shardFailures);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardExistsResponse shardOperation(ShardExistsRequest request) {
|
||||
IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex());
|
||||
IndexShard indexShard = indexService.getShard(request.shardId().id());
|
||||
|
||||
SearchShardTarget shardTarget = new SearchShardTarget(clusterService.localNode().id(), request.shardId().getIndex(), request.shardId().id());
|
||||
SearchContext context = new DefaultSearchContext(0,
|
||||
new ShardSearchLocalRequest(request.types(), request.nowInMillis(), request.filteringAliases()),
|
||||
shardTarget, indexShard.acquireSearcher("exists"), indexService, indexShard,
|
||||
scriptService, pageCacheRecycler, bigArrays, threadPool.estimatedTimeInMillisCounter(), parseFieldMatcher,
|
||||
SearchService.NO_TIMEOUT
|
||||
);
|
||||
SearchContext.setCurrent(context);
|
||||
|
||||
try {
|
||||
if (request.minScore() != DEFAULT_MIN_SCORE) {
|
||||
context.minimumScore(request.minScore());
|
||||
}
|
||||
BytesReference source = request.querySource();
|
||||
if (source != null && source.length() > 0) {
|
||||
try {
|
||||
QueryShardContext.setTypes(request.types());
|
||||
context.parsedQuery(indexService.queryParserService().parseQuery(source));
|
||||
} finally {
|
||||
QueryShardContext.removeTypes();
|
||||
}
|
||||
}
|
||||
context.preProcess();
|
||||
try {
|
||||
boolean exists;
|
||||
try {
|
||||
exists = Lucene.exists(context.searcher(), context.query());
|
||||
} finally {
|
||||
context.clearReleasables(SearchContext.Lifetime.COLLECTION);
|
||||
}
|
||||
return new ShardExistsResponse(request.shardId(), exists);
|
||||
} catch (Exception e) {
|
||||
throw new QueryPhaseExecutionException(context, "failed to execute exists", e);
|
||||
}
|
||||
} finally {
|
||||
// this will also release the index searcher
|
||||
context.close();
|
||||
SearchContext.removeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An async broadcast action that early terminates shard request
|
||||
* upon any shard response reporting matched doc existence
|
||||
*/
|
||||
final private class ExistsAsyncBroadcastAction extends AsyncBroadcastAction {
|
||||
|
||||
final AtomicBoolean processed = new AtomicBoolean(false);
|
||||
|
||||
ExistsAsyncBroadcastAction(ExistsRequest request, ActionListener<ExistsResponse> listener) {
|
||||
super(request, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOperation(ShardRouting shard, int shardIndex, ShardExistsResponse response) {
|
||||
super.onOperation(shard, shardIndex, response);
|
||||
if (response.exists()) {
|
||||
finishHim();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperation(final ShardIterator shardIt, final ShardRouting shard, final int shardIndex) {
|
||||
if (processed.get()) {
|
||||
return;
|
||||
}
|
||||
super.performOperation(shardIt, shard, shardIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishHim() {
|
||||
if (processed.compareAndSet(false, true)) {
|
||||
super.finishHim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exists action.
|
||||
*/
|
||||
package org.elasticsearch.action.exists;
|
|
@ -27,9 +27,6 @@ import org.elasticsearch.action.bulk.BulkResponse;
|
|||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequestBuilder;
|
||||
import org.elasticsearch.action.delete.DeleteResponse;
|
||||
import org.elasticsearch.action.exists.ExistsRequest;
|
||||
import org.elasticsearch.action.exists.ExistsRequestBuilder;
|
||||
import org.elasticsearch.action.exists.ExistsResponse;
|
||||
import org.elasticsearch.action.explain.ExplainRequest;
|
||||
import org.elasticsearch.action.explain.ExplainRequestBuilder;
|
||||
import org.elasticsearch.action.explain.ExplainResponse;
|
||||
|
@ -334,29 +331,6 @@ public interface Client extends ElasticsearchClient, Releasable {
|
|||
*/
|
||||
MultiGetRequestBuilder prepareMultiGet();
|
||||
|
||||
/**
|
||||
* Checks existence of any documents matching a specific query.
|
||||
*
|
||||
* @param request The exists request
|
||||
* @return The result future
|
||||
* @see Requests#existsRequest(String...)
|
||||
*/
|
||||
ActionFuture<ExistsResponse> exists(ExistsRequest request);
|
||||
|
||||
/**
|
||||
* Checks existence of any documents matching a specific query.
|
||||
*
|
||||
* @param request The exists request
|
||||
* @param listener A listener to be notified of the result
|
||||
* @see Requests#existsRequest(String...)
|
||||
*/
|
||||
void exists(ExistsRequest request, ActionListener<ExistsResponse> listener);
|
||||
|
||||
/**
|
||||
* Checks existence of any documents matching a specific query.
|
||||
*/
|
||||
ExistsRequestBuilder prepareExists(String... indices);
|
||||
|
||||
/**
|
||||
* Suggestion matching a specific phrase.
|
||||
*
|
||||
|
|
|
@ -53,7 +53,6 @@ import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresRequest;
|
|||
import org.elasticsearch.action.admin.indices.upgrade.post.UpgradeRequest;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.exists.ExistsRequest;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
|
@ -123,18 +122,6 @@ public class Requests {
|
|||
return new GetRequest(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a exists request which checks if any of the hits matched against a query exists. Note, the query itself must be set
|
||||
* either using the JSON source of the query, or using a {@link org.elasticsearch.index.query.QueryBuilder} (using {@link org.elasticsearch.index.query.QueryBuilders}).
|
||||
*
|
||||
* @param indices The indices to count matched documents against a query. Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
|
||||
* @return The exists request
|
||||
* @see org.elasticsearch.client.Client#exists(org.elasticsearch.action.exists.ExistsRequest)
|
||||
*/
|
||||
public static ExistsRequest existsRequest(String... indices) {
|
||||
return new ExistsRequest(indices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a suggest request for getting suggestions from provided <code>indices</code>.
|
||||
* The suggest query has to be set using the JSON source using {@link org.elasticsearch.action.suggest.SuggestRequest#suggest(org.elasticsearch.common.bytes.BytesReference)}.
|
||||
|
|
|
@ -232,10 +232,6 @@ import org.elasticsearch.action.delete.DeleteAction;
|
|||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequestBuilder;
|
||||
import org.elasticsearch.action.delete.DeleteResponse;
|
||||
import org.elasticsearch.action.exists.ExistsAction;
|
||||
import org.elasticsearch.action.exists.ExistsRequest;
|
||||
import org.elasticsearch.action.exists.ExistsRequestBuilder;
|
||||
import org.elasticsearch.action.exists.ExistsResponse;
|
||||
import org.elasticsearch.action.explain.ExplainAction;
|
||||
import org.elasticsearch.action.explain.ExplainRequest;
|
||||
import org.elasticsearch.action.explain.ExplainRequestBuilder;
|
||||
|
@ -601,21 +597,6 @@ public abstract class AbstractClient extends AbstractComponent implements Client
|
|||
return new MultiSearchRequestBuilder(this, MultiSearchAction.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFuture<ExistsResponse> exists(final ExistsRequest request) {
|
||||
return execute(ExistsAction.INSTANCE, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exists(final ExistsRequest request, final ActionListener<ExistsResponse> listener) {
|
||||
execute(ExistsAction.INSTANCE, request, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExistsRequestBuilder prepareExists(String... indices) {
|
||||
return new ExistsRequestBuilder(this, ExistsAction.INSTANCE).setIndices(indices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFuture<SuggestResponse> suggest(final SuggestRequest request) {
|
||||
return execute(SuggestAction.INSTANCE, request);
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.rest.action.exists;
|
||||
|
||||
import org.elasticsearch.action.exists.ExistsRequest;
|
||||
import org.elasticsearch.action.exists.ExistsResponse;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.support.QuerySourceBuilder;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestActions;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
|
||||
import static org.elasticsearch.action.exists.ExistsRequest.DEFAULT_MIN_SCORE;
|
||||
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
|
||||
/**
|
||||
* Action for /_search/exists endpoint
|
||||
*/
|
||||
public class RestExistsAction extends BaseRestHandler {
|
||||
|
||||
public RestExistsAction(Settings settings, RestController controller, Client client) {
|
||||
super(settings, controller, client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) {
|
||||
final ExistsRequest existsRequest = new ExistsRequest(Strings.splitStringByCommaToArray(request.param("index")));
|
||||
existsRequest.indicesOptions(IndicesOptions.fromRequest(request, existsRequest.indicesOptions()));
|
||||
if (RestActions.hasBodyContent(request)) {
|
||||
existsRequest.source(RestActions.getRestContent(request));
|
||||
} else {
|
||||
QueryBuilder<?> queryBuilder = RestActions.urlParamsToQueryBuilder(request);
|
||||
if (queryBuilder != null) {
|
||||
QuerySourceBuilder querySourceBuilder = new QuerySourceBuilder();
|
||||
querySourceBuilder.setQuery(queryBuilder);
|
||||
existsRequest.source(querySourceBuilder.buildAsBytes());
|
||||
}
|
||||
}
|
||||
existsRequest.routing(request.param("routing"));
|
||||
existsRequest.minScore(request.paramAsFloat("min_score", DEFAULT_MIN_SCORE));
|
||||
existsRequest.types(Strings.splitStringByCommaToArray(request.param("type")));
|
||||
existsRequest.preference(request.param("preference"));
|
||||
|
||||
client.exists(existsRequest, new RestBuilderListener<ExistsResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(ExistsResponse response, XContentBuilder builder) throws Exception {
|
||||
RestStatus status = response.exists() ? OK : NOT_FOUND;
|
||||
builder.startObject();
|
||||
builder.field("exists", response.exists());
|
||||
builder.endObject();
|
||||
return new BytesRestResponse(status, builder);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -38,7 +38,6 @@ import org.elasticsearch.rest.BaseRestHandler;
|
|||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.exists.RestExistsAction;
|
||||
import org.elasticsearch.rest.action.support.RestActions;
|
||||
import org.elasticsearch.rest.action.support.RestStatusToXContentListener;
|
||||
import org.elasticsearch.script.Template;
|
||||
|
@ -80,14 +79,6 @@ public class RestSearchAction extends BaseRestHandler {
|
|||
controller.registerHandler(POST, "/{index}/_search/template", this);
|
||||
controller.registerHandler(GET, "/{index}/{type}/_search/template", this);
|
||||
controller.registerHandler(POST, "/{index}/{type}/_search/template", this);
|
||||
|
||||
RestExistsAction restExistsAction = new RestExistsAction(settings, controller, client);
|
||||
controller.registerHandler(GET, "/_search/exists", restExistsAction);
|
||||
controller.registerHandler(POST, "/_search/exists", restExistsAction);
|
||||
controller.registerHandler(GET, "/{index}/_search/exists", restExistsAction);
|
||||
controller.registerHandler(POST, "/{index}/_search/exists", restExistsAction);
|
||||
controller.registerHandler(GET, "/{index}/{type}/_search/exists", restExistsAction);
|
||||
controller.registerHandler(POST, "/{index}/{type}/_search/exists", restExistsAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.exists;
|
||||
|
||||
import org.elasticsearch.action.exists.ExistsResponse;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertExists;
|
||||
|
||||
public class SimpleExistsIT extends ESIntegTestCase {
|
||||
public void testExistsRandomPreference() throws Exception {
|
||||
createIndex("test");
|
||||
indexRandom(true, client().prepareIndex("test", "type", "1").setSource("field", "value"),
|
||||
client().prepareIndex("test", "type", "2").setSource("field", "value"),
|
||||
client().prepareIndex("test", "type", "3").setSource("field", "value"),
|
||||
client().prepareIndex("test", "type", "4").setSource("field", "value"),
|
||||
client().prepareIndex("test", "type", "5").setSource("field", "value"),
|
||||
client().prepareIndex("test", "type", "6").setSource("field", "value"));
|
||||
|
||||
int iters = scaledRandomIntBetween(10, 100);
|
||||
for (int i = 0; i < iters; i++) {
|
||||
|
||||
String randomPreference = randomUnicodeOfLengthBetween(0, 4);
|
||||
// randomPreference should not start with '_' (reserved for known preference types (e.g. _shards, _primary)
|
||||
while (randomPreference.startsWith("_")) {
|
||||
randomPreference = randomUnicodeOfLengthBetween(0, 4);
|
||||
}
|
||||
// id is not indexed, but lets see that we automatically convert to
|
||||
ExistsResponse existsResponse = client().prepareExists().setQuery(QueryBuilders.matchAllQuery()).setPreference(randomPreference).get();
|
||||
assertExists(existsResponse, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSimpleIp() throws Exception {
|
||||
createIndex("test");
|
||||
|
||||
client().admin().indices().preparePutMapping("test").setType("type1")
|
||||
.setSource(XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
|
||||
.startObject("from").field("type", "ip").endObject()
|
||||
.startObject("to").field("type", "ip").endObject()
|
||||
.endObject().endObject().endObject())
|
||||
.execute().actionGet();
|
||||
|
||||
client().prepareIndex("test", "type1", "1").setSource("from", "192.168.0.5", "to", "192.168.0.10").setRefresh(true).execute().actionGet();
|
||||
|
||||
ExistsResponse existsResponse = client().prepareExists()
|
||||
.setQuery(boolQuery().must(rangeQuery("from").lt("192.168.0.7")).must(rangeQuery("to").gt("192.168.0.7"))).get();
|
||||
|
||||
assertExists(existsResponse, true);
|
||||
|
||||
existsResponse = client().prepareExists().setQuery(boolQuery().must(rangeQuery("from").lt("192.168.0.4")).must(rangeQuery("to").gt("192.168.0.11"))).get();
|
||||
|
||||
assertExists(existsResponse, false);
|
||||
}
|
||||
|
||||
public void testSimpleId() {
|
||||
createIndex("test");
|
||||
|
||||
client().prepareIndex("test", "type", "XXX1").setSource("field", "value").setRefresh(true).execute().actionGet();
|
||||
// id is not indexed, but lets see that we automatically convert to
|
||||
ExistsResponse existsResponse = client().prepareExists().setQuery(QueryBuilders.termQuery("_id", "XXX1")).execute().actionGet();
|
||||
assertExists(existsResponse, true);
|
||||
|
||||
existsResponse = client().prepareExists().setQuery(QueryBuilders.queryStringQuery("_id:XXX1")).execute().actionGet();
|
||||
assertExists(existsResponse, true);
|
||||
|
||||
existsResponse = client().prepareExists().setQuery(QueryBuilders.prefixQuery("_id", "XXX")).execute().actionGet();
|
||||
assertExists(existsResponse, true);
|
||||
|
||||
existsResponse = client().prepareExists().setQuery(QueryBuilders.queryStringQuery("_id:XXX*").lowercaseExpandedTerms(false)).execute().actionGet();
|
||||
assertExists(existsResponse, true);
|
||||
}
|
||||
|
||||
public void testSimpleNonExistence() throws Exception {
|
||||
createIndex("test");
|
||||
client().prepareIndex("test", "type1", "1").setSource("field", 2).execute().actionGet();
|
||||
client().prepareIndex("test", "type1", "2").setSource("field", 5).execute().actionGet();
|
||||
client().prepareIndex("test", "type", "XXX1").setSource("str_field", "value").execute().actionGet();
|
||||
ensureGreen();
|
||||
refresh();
|
||||
ExistsResponse existsResponse = client().prepareExists("test").setQuery(QueryBuilders.rangeQuery("field").gte(6).lte(8)).execute().actionGet();
|
||||
assertExists(existsResponse, false);
|
||||
|
||||
existsResponse = client().prepareExists("test").setQuery(QueryBuilders.queryStringQuery("_id:XXY*").lowercaseExpandedTerms(false)).execute().actionGet();
|
||||
assertExists(existsResponse, false);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,6 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
|
|||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.exists.ExistsResponse;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.percolate.PercolateResponse;
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
|
@ -251,13 +250,6 @@ public class ElasticsearchAssertions {
|
|||
assertVersionSerializable(countResponse);
|
||||
}
|
||||
|
||||
public static void assertExists(ExistsResponse existsResponse, boolean expected) {
|
||||
if (existsResponse.exists() != expected) {
|
||||
fail("Exist is " + existsResponse.exists() + " but " + expected + " was expected " + formatShardStatus(existsResponse));
|
||||
}
|
||||
assertVersionSerializable(existsResponse);
|
||||
}
|
||||
|
||||
public static void assertMatchCount(PercolateResponse percolateResponse, long expectedHitCount) {
|
||||
if (percolateResponse.getCount() != expectedHitCount) {
|
||||
fail("Count is " + percolateResponse.getCount() + " but " + expectedHitCount + " was expected. " + formatShardStatus(percolateResponse));
|
||||
|
|
|
@ -63,6 +63,11 @@ Scroll requests sorted by `_doc` have been optimized to more efficiently resume
|
|||
from where the previous request stopped, so this will have the same performance
|
||||
characteristics as the former `scan` search type.
|
||||
|
||||
==== search exists api removed
|
||||
|
||||
The search exists api has been removed in favour of using the search api with
|
||||
`size` set to `0` and `terminate_after` set to `1`.
|
||||
|
||||
=== Parent/Child changes
|
||||
|
||||
The `children` aggregation, parent child inner hits and `has_child` and `has_parent` queries will not work on indices
|
||||
|
|
|
@ -91,8 +91,6 @@ include::search/multi-search.asciidoc[]
|
|||
|
||||
include::search/count.asciidoc[]
|
||||
|
||||
include::search/exists.asciidoc[]
|
||||
|
||||
include::search/validate.asciidoc[]
|
||||
|
||||
include::search/explain.asciidoc[]
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
[[search-exists]]
|
||||
== Search Exists API
|
||||
|
||||
The exists API allows to easily determine if any
|
||||
matching documents exist for a provided query. It can be executed across one or more indices
|
||||
and across one or more types. The query can either be provided using a
|
||||
simple query string as a parameter, or using the
|
||||
<<query-dsl,Query DSL>> defined within the request
|
||||
body. Here is an example:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
$ curl -XGET 'http://localhost:9200/twitter/tweet/_search/exists?q=user:kimchy'
|
||||
|
||||
$ curl -XGET 'http://localhost:9200/twitter/tweet/_search/exists' -d '
|
||||
{
|
||||
"query" : {
|
||||
"term" : { "user" : "kimchy" }
|
||||
}
|
||||
}'
|
||||
|
||||
--------------------------------------------------
|
||||
|
||||
NOTE: The query being sent in the body must be nested in a `query` key, same as
|
||||
how the <<search-search,search api>> works.
|
||||
|
||||
Both the examples above do the same thing, which is determine the existence of
|
||||
tweets from the twitter index for a certain user. The response body will be of
|
||||
the following format:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
{
|
||||
"exists" : true
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
[float]
|
||||
=== Multi index, Multi type
|
||||
|
||||
The exists API can be applied to <<search-multi-index-type,multiple types in multiple indices>>.
|
||||
|
||||
[float]
|
||||
=== Request Parameters
|
||||
|
||||
When executing exists using the query parameter `q`, the query passed is
|
||||
a query string using Lucene query parser. There are additional
|
||||
parameters that can be passed:
|
||||
|
||||
[cols="<,<",options="header",]
|
||||
|=======================================================================
|
||||
|Name |Description
|
||||
|`df` |The default field to use when no field prefix is defined within the
|
||||
query.
|
||||
|
||||
|`analyzer` |The analyzer name to be used when analyzing the query string.
|
||||
|
||||
|`default_operator` |The default operator to be used, can be `AND` or
|
||||
`OR`. Defaults to `OR`.
|
||||
|
||||
|`lenient` |If set to true will cause format based failures (like
|
||||
providing text to a numeric field) to be ignored. Defaults to false.
|
||||
|
||||
|`lowercase_expanded_terms` |Should terms be automatically lowercased or
|
||||
not. Defaults to `true`.
|
||||
|
||||
|`analyze_wildcard` |Should wildcard and prefix queries be analyzed or
|
||||
not. Defaults to `false`.
|
||||
|=======================================================================
|
||||
|
||||
[float]
|
||||
=== Request Body
|
||||
|
||||
The exists API can use the <<query-dsl,Query DSL>> within
|
||||
its body in order to express the query that should be executed. The body
|
||||
content can also be passed as a REST parameter named `source`.
|
||||
|
||||
HTTP GET and HTTP POST can be used to execute exists with body.
|
||||
Since not all clients support GET with body, POST is allowed as well.
|
||||
|
||||
[float]
|
||||
=== Distributed
|
||||
|
||||
The exists operation is broadcast across all shards. For each shard id
|
||||
group, a replica is chosen and executed against it. This means that
|
||||
replicas increase the scalability of exists. The exists operation also
|
||||
early terminates shard requests once the first shard reports matched
|
||||
document existence.
|
||||
|
||||
[float]
|
||||
=== Routing
|
||||
|
||||
The routing value (a comma separated list of the routing values) can be
|
||||
specified to control which shards the exists request will be executed on.
|
|
@ -59,8 +59,6 @@ import org.elasticsearch.action.bulk.BulkAction;
|
|||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.delete.DeleteAction;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.exists.ExistsAction;
|
||||
import org.elasticsearch.action.exists.ExistsRequest;
|
||||
import org.elasticsearch.action.explain.ExplainAction;
|
||||
import org.elasticsearch.action.explain.ExplainRequest;
|
||||
import org.elasticsearch.action.get.GetAction;
|
||||
|
@ -363,17 +361,6 @@ public class IndicesRequestTests extends ESIntegTestCase {
|
|||
assertIndicesSubset(indices, multiGetShardAction);
|
||||
}
|
||||
|
||||
public void testExists() {
|
||||
String existsShardAction = ExistsAction.NAME + "[s]";
|
||||
interceptTransportActions(existsShardAction);
|
||||
|
||||
ExistsRequest existsRequest = new ExistsRequest(randomIndicesOrAliases());
|
||||
internalCluster().clientNodeClient().exists(existsRequest).actionGet();
|
||||
|
||||
clearInterceptedActions();
|
||||
assertSameIndices(existsRequest, existsShardAction);
|
||||
}
|
||||
|
||||
public void testFlush() {
|
||||
String[] indexShardActions = new String[]{TransportShardFlushAction.NAME + "[r]", TransportShardFlushAction.NAME};
|
||||
interceptTransportActions(indexShardActions);
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
{
|
||||
"search_exists": {
|
||||
"documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-exists.html",
|
||||
"methods": ["POST", "GET"],
|
||||
"url": {
|
||||
"path": "/_search/exists",
|
||||
"paths": ["/_search/exists", "/{index}/_search/exists", "/{index}/{type}/_search/exists"],
|
||||
"parts": {
|
||||
"index": {
|
||||
"type" : "list",
|
||||
"description" : "A comma-separated list of indices to restrict the results"
|
||||
},
|
||||
"type": {
|
||||
"type" : "list",
|
||||
"description" : "A comma-separated list of types to restrict the results"
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"ignore_unavailable": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether specified concrete indices should be ignored when unavailable (missing or closed)"
|
||||
},
|
||||
"allow_no_indices": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)"
|
||||
},
|
||||
"expand_wildcards": {
|
||||
"type" : "enum",
|
||||
"options" : ["open","closed","none","all"],
|
||||
"default" : "open",
|
||||
"description" : "Whether to expand wildcard expression to concrete indices that are open, closed or both."
|
||||
},
|
||||
"min_score": {
|
||||
"type" : "number",
|
||||
"description" : "Include only documents with a specific `_score` value in the result"
|
||||
},
|
||||
"preference": {
|
||||
"type" : "string",
|
||||
"description" : "Specify the node or shard the operation should be performed on (default: random)"
|
||||
},
|
||||
"routing": {
|
||||
"type" : "string",
|
||||
"description" : "Specific routing value"
|
||||
},
|
||||
"q": {
|
||||
"type" : "string",
|
||||
"description" : "Query in the Lucene query string syntax"
|
||||
},
|
||||
"analyzer": {
|
||||
"type" : "string",
|
||||
"description" : "The analyzer to use for the query string"
|
||||
},
|
||||
"analyze_wildcard": {
|
||||
"type" : "boolean",
|
||||
"description" : "Specify whether wildcard and prefix queries should be analyzed (default: false)"
|
||||
},
|
||||
"default_operator": {
|
||||
"type" : "enum",
|
||||
"options" : ["AND","OR"],
|
||||
"default" : "OR",
|
||||
"description" : "The default operator for query string query (AND or OR)"
|
||||
},
|
||||
"df": {
|
||||
"type" : "string",
|
||||
"description" : "The field to use as default where no field prefix is given in the query string"
|
||||
},
|
||||
"lenient": {
|
||||
"type" : "boolean",
|
||||
"description" : "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored"
|
||||
},
|
||||
"lowercase_expanded_terms": {
|
||||
"type" : "boolean",
|
||||
"description" : "Specify whether query terms should be lowercased"
|
||||
}
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"description" : "A query to restrict the results specified with the Query DSL (optional)"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
"search_exists with body":
|
||||
- do:
|
||||
indices.create:
|
||||
index: test
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body: { foo: bar }
|
||||
|
||||
- do:
|
||||
indices.refresh:
|
||||
index: [test]
|
||||
|
||||
- do:
|
||||
search_exists:
|
||||
index: test
|
||||
type: test
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
foo: bar
|
||||
|
||||
- is_true: exists
|
||||
|
||||
- do:
|
||||
catch: missing
|
||||
search_exists:
|
||||
index: test
|
||||
type: test
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
foo: test
|
||||
|
||||
- is_false: exists
|
|
@ -1,82 +0,0 @@
|
|||
---
|
||||
"search_exists with query_string parameters":
|
||||
- do:
|
||||
indices.create:
|
||||
index: test
|
||||
body:
|
||||
mappings:
|
||||
test:
|
||||
_all:
|
||||
enabled: false
|
||||
properties:
|
||||
number:
|
||||
type: integer
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body: { field: foo bar}
|
||||
|
||||
- do:
|
||||
indices.refresh:
|
||||
index: [test]
|
||||
|
||||
- do:
|
||||
search_exists:
|
||||
index: test
|
||||
q: bar
|
||||
df: field
|
||||
|
||||
- is_true: exists
|
||||
|
||||
- do:
|
||||
search_exists:
|
||||
index: test
|
||||
q: field:foo field:xyz
|
||||
|
||||
- is_true: exists
|
||||
|
||||
- do:
|
||||
catch: missing
|
||||
search_exists:
|
||||
index: test
|
||||
q: field:foo field:xyz
|
||||
default_operator: AND
|
||||
|
||||
- is_false: exists
|
||||
|
||||
- do:
|
||||
search_exists:
|
||||
index: test
|
||||
q: field:bars
|
||||
analyzer: snowball
|
||||
|
||||
- is_true: exists
|
||||
|
||||
- do:
|
||||
catch: missing
|
||||
search_exists:
|
||||
index: test
|
||||
q: field:BA*
|
||||
lowercase_expanded_terms: false
|
||||
|
||||
- is_false: exists
|
||||
|
||||
- do:
|
||||
search_exists:
|
||||
index: test
|
||||
q: field:BA*
|
||||
analyze_wildcard: true
|
||||
|
||||
- is_true: exists
|
||||
|
||||
- do:
|
||||
catch: missing
|
||||
search_exists:
|
||||
index: test
|
||||
q: number:foo
|
||||
lenient: true
|
||||
|
||||
- is_false: exists
|
Loading…
Reference in New Issue