Mapping API: Delete Mapping (with data), closes #373.

This commit is contained in:
kimchy 2010-09-16 14:35:07 +02:00
parent aef4704fed
commit f49f3e169a
25 changed files with 791 additions and 50 deletions

View File

@ -36,6 +36,7 @@ import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
import org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction;
import org.elasticsearch.action.admin.indices.flush.TransportFlushAction;
import org.elasticsearch.action.admin.indices.gateway.snapshot.TransportGatewaySnapshotAction;
import org.elasticsearch.action.admin.indices.mapping.delete.TransportDeleteMappingAction;
import org.elasticsearch.action.admin.indices.mapping.put.TransportPutMappingAction;
import org.elasticsearch.action.admin.indices.optimize.TransportOptimizeAction;
import org.elasticsearch.action.admin.indices.refresh.TransportRefreshAction;
@ -78,8 +79,9 @@ public class TransportActionModule extends AbstractModule {
bind(TransportIndicesStatusAction.class).asEagerSingleton();
bind(TransportCreateIndexAction.class).asEagerSingleton();
bind(TransportPutMappingAction.class).asEagerSingleton();
bind(TransportDeleteIndexAction.class).asEagerSingleton();
bind(TransportPutMappingAction.class).asEagerSingleton();
bind(TransportDeleteMappingAction.class).asEagerSingleton();
bind(TransportIndicesAliasesAction.class).asEagerSingleton();
bind(TransportUpdateSettingsAction.class).asEagerSingleton();

View File

@ -62,6 +62,7 @@ public class TransportActions {
public static class Mapping {
public static final String PUT = "indices/mapping/put";
public static final String DELETE = "indices/mapping/delete";
}
public static class Cache {

View File

@ -0,0 +1,117 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.admin.indices.mapping.delete;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import static org.elasticsearch.action.Actions.*;
/**
* @author kimchy (shay.banon)
*/
public class DeleteMappingRequest extends MasterNodeOperationRequest {
private String[] indices;
private String mappingType;
DeleteMappingRequest() {
}
/**
* Constructs a new put mapping request against one or more indices. If nothing is set then
* it will be executed against all indices.
*/
public DeleteMappingRequest(String... indices) {
this.indices = indices;
}
@Override public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (mappingType == null) {
validationException = addValidationError("mapping type is missing", validationException);
}
return validationException;
}
/**
* Sets the indices this put mapping operation will execute on.
*/
public DeleteMappingRequest indices(String[] indices) {
this.indices = indices;
return this;
}
/**
* The indices the mappings will be put.
*/
public String[] indices() {
return indices;
}
/**
* The mapping type.
*/
public String type() {
return mappingType;
}
/**
* The type of the mappings to remove.
*/
public DeleteMappingRequest type(String mappingType) {
this.mappingType = mappingType;
return this;
}
@Override public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
indices = new String[in.readVInt()];
for (int i = 0; i < indices.length; i++) {
indices[i] = in.readUTF();
}
if (in.readBoolean()) {
mappingType = in.readUTF();
}
}
@Override public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
if (indices == null) {
out.writeVInt(0);
} else {
out.writeVInt(indices.length);
for (String index : indices) {
out.writeUTF(index);
}
}
if (mappingType == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeUTF(mappingType);
}
}
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.admin.indices.mapping.delete;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
import java.io.IOException;
/**
* The response of remove mapping operation.
*
* @author kimchy (shay.banon)
*/
public class DeleteMappingResponse implements ActionResponse, Streamable {
DeleteMappingResponse() {
}
@Override public void readFrom(StreamInput in) throws IOException {
}
@Override public void writeTo(StreamOutput out) throws IOException {
}
}

View File

@ -0,0 +1,116 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.admin.indices.mapping.delete;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.deletebyquery.TransportDeleteByQueryAction;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.MetaDataMappingService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.mapper.TypeFieldMapper;
import org.elasticsearch.index.query.xcontent.FilterBuilders;
import org.elasticsearch.index.query.xcontent.QueryBuilders;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
/**
* Delete mapping action.
*
* @author kimchy (shay.banon)
*/
public class TransportDeleteMappingAction extends TransportMasterNodeOperationAction<DeleteMappingRequest, DeleteMappingResponse> {
private final MetaDataMappingService metaDataMappingService;
private final TransportDeleteByQueryAction deleteByQueryAction;
@Inject public TransportDeleteMappingAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, MetaDataMappingService metaDataMappingService, TransportDeleteByQueryAction deleteByQueryAction) {
super(settings, transportService, clusterService, threadPool);
this.metaDataMappingService = metaDataMappingService;
this.deleteByQueryAction = deleteByQueryAction;
}
@Override protected String transportAction() {
return TransportActions.Admin.Indices.Mapping.DELETE;
}
@Override protected DeleteMappingRequest newRequest() {
return new DeleteMappingRequest();
}
@Override protected DeleteMappingResponse newResponse() {
return new DeleteMappingResponse();
}
@Override protected void checkBlock(DeleteMappingRequest request, ClusterState state) {
// update to concrete indices
request.indices(state.metaData().concreteIndices(request.indices()));
for (String index : request.indices()) {
state.blocks().indexBlockedRaiseException(ClusterBlockLevel.METADATA, index);
}
}
@Override protected DeleteMappingResponse masterOperation(final DeleteMappingRequest request, final ClusterState state) throws ElasticSearchException {
final AtomicReference<Throwable> failureRef = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(1);
deleteByQueryAction.execute(Requests.deleteByQueryRequest(request.indices()).query(QueryBuilders.filtered(QueryBuilders.matchAllQuery(), FilterBuilders.termFilter(TypeFieldMapper.NAME, request.type()))), new ActionListener<DeleteByQueryResponse>() {
@Override public void onResponse(DeleteByQueryResponse deleteByQueryResponse) {
metaDataMappingService.removeMapping(new MetaDataMappingService.RemoveRequest(request.indices(), request.type()));
latch.countDown();
}
@Override public void onFailure(Throwable e) {
failureRef.set(e);
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
failureRef.set(e);
}
if (failureRef.get() != null) {
if (failureRef.get() instanceof ElasticSearchException) {
throw (ElasticSearchException) failureRef.get();
} else {
throw new ElasticSearchException(failureRef.get().getMessage(), failureRef.get());
}
}
return new DeleteMappingResponse();
}
}

View File

@ -81,7 +81,7 @@ public class TransportPutMappingAction extends TransportMasterNodeOperationActio
final AtomicReference<PutMappingResponse> responseRef = new AtomicReference<PutMappingResponse>();
final AtomicReference<Throwable> failureRef = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(1);
metaDataMappingService.putMapping(new MetaDataMappingService.Request(request.indices(), request.type(), request.source()).ignoreConflicts(request.ignoreConflicts()).timeout(request.timeout()), new MetaDataMappingService.Listener() {
metaDataMappingService.putMapping(new MetaDataMappingService.PutRequest(request.indices(), request.type(), request.source()).ignoreConflicts(request.ignoreConflicts()).timeout(request.timeout()), new MetaDataMappingService.Listener() {
@Override public void onResponse(MetaDataMappingService.Response response) {
responseRef.set(new PutMappingResponse(response.acknowledged()));
latch.countDown();

View File

@ -33,6 +33,8 @@ import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotRequest;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotResponse;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.optimize.OptimizeRequest;
@ -49,6 +51,7 @@ import org.elasticsearch.client.action.admin.indices.create.CreateIndexRequestBu
import org.elasticsearch.client.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.client.action.admin.indices.flush.FlushRequestBuilder;
import org.elasticsearch.client.action.admin.indices.gateway.snapshot.GatewaySnapshotRequestBuilder;
import org.elasticsearch.client.action.admin.indices.mapping.delete.DeleteMappingRequestBuilder;
import org.elasticsearch.client.action.admin.indices.mapping.put.PutMappingRequestBuilder;
import org.elasticsearch.client.action.admin.indices.optimize.OptimizeRequestBuilder;
import org.elasticsearch.client.action.admin.indices.refresh.RefreshRequestBuilder;
@ -228,6 +231,29 @@ public interface IndicesAdminClient {
*/
PutMappingRequestBuilder preparePutMapping(String... indices);
/**
* Deletes mapping (and all its data) from one or more indices.
*
* @param request The delete mapping request
* @return A result future
* @see org.elasticsearch.client.Requests#deleteMappingRequest(String...)
*/
ActionFuture<DeleteMappingResponse> deleteMapping(DeleteMappingRequest request);
/**
* Deletes mapping definition for a type into one or more indices.
*
* @param request The delete mapping request
* @param listener A listener to be notified with a result
* @see org.elasticsearch.client.Requests#deleteMappingRequest(String...)
*/
void deleteMapping(DeleteMappingRequest request, ActionListener<DeleteMappingResponse> listener);
/**
* Deletes mapping definition for a type into one or more indices.
*/
DeleteMappingRequestBuilder prepareDeleteMapping(String... indices);
/**
* Explicitly perform gateway snapshot for one or more indices.
*

View File

@ -34,6 +34,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.optimize.OptimizeRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
@ -212,6 +213,17 @@ public class Requests {
return new PutMappingRequest(indices);
}
/**
* Deletes mapping (and all its data) from one or more indices.
*
* @param indices The indices the mapping will be deleted from. Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
* @return The create mapping request
* @see org.elasticsearch.client.IndicesAdminClient#deleteMapping(org.elasticsearch.action.admin.indices.mapping.put.DeleteMappingRequest)
*/
public static DeleteMappingRequest deleteMappingRequest(String... indices) {
return new DeleteMappingRequest(indices);
}
/**
* Creates an index aliases request allowing to add and remove aliases.
*

View File

@ -0,0 +1,62 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.client.action.admin.indices.mapping.delete;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingResponse;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.action.admin.indices.support.BaseIndicesRequestBuilder;
import org.elasticsearch.common.unit.TimeValue;
/**
* @author kimchy (shay.banon)
*/
public class DeleteMappingRequestBuilder extends BaseIndicesRequestBuilder<DeleteMappingRequest, DeleteMappingResponse> {
public DeleteMappingRequestBuilder(IndicesAdminClient indicesClient) {
super(indicesClient, new DeleteMappingRequest());
}
public DeleteMappingRequestBuilder setIndices(String... indices) {
request.indices(indices);
return this;
}
/**
* The type of the mapping to remove.
*/
public DeleteMappingRequestBuilder setType(String type) {
request.type(type);
return this;
}
/**
* Sets the master node timeout in case the master has not yet been discovered.
*/
public DeleteMappingRequestBuilder setMasterNodeTimeout(TimeValue timeout) {
request.masterNodeTimeout(timeout);
return this;
}
@Override protected void doExecute(ActionListener<DeleteMappingResponse> listener) {
client.deleteMapping(request, listener);
}
}

View File

@ -39,6 +39,9 @@ import org.elasticsearch.action.admin.indices.flush.TransportFlushAction;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotRequest;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotResponse;
import org.elasticsearch.action.admin.indices.gateway.snapshot.TransportGatewaySnapshotAction;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingResponse;
import org.elasticsearch.action.admin.indices.mapping.delete.TransportDeleteMappingAction;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.mapping.put.TransportPutMappingAction;
@ -81,6 +84,8 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
private final TransportPutMappingAction putMappingAction;
private final TransportDeleteMappingAction deleteMappingAction;
private final TransportGatewaySnapshotAction gatewaySnapshotAction;
private final TransportIndicesAliasesAction indicesAliasesAction;
@ -92,7 +97,7 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
@Inject public NodeIndicesAdminClient(Settings settings, ThreadPool threadPool, TransportIndicesStatusAction indicesStatusAction,
TransportCreateIndexAction createIndexAction, TransportDeleteIndexAction deleteIndexAction,
TransportRefreshAction refreshAction, TransportFlushAction flushAction, TransportOptimizeAction optimizeAction,
TransportPutMappingAction putMappingAction, TransportGatewaySnapshotAction gatewaySnapshotAction,
TransportPutMappingAction putMappingAction, TransportDeleteMappingAction deleteMappingAction, TransportGatewaySnapshotAction gatewaySnapshotAction,
TransportIndicesAliasesAction indicesAliasesAction, TransportClearIndicesCacheAction clearIndicesCacheAction,
TransportUpdateSettingsAction updateSettingsAction) {
this.threadPool = threadPool;
@ -102,6 +107,7 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
this.refreshAction = refreshAction;
this.flushAction = flushAction;
this.optimizeAction = optimizeAction;
this.deleteMappingAction = deleteMappingAction;
this.putMappingAction = putMappingAction;
this.gatewaySnapshotAction = gatewaySnapshotAction;
this.indicesAliasesAction = indicesAliasesAction;
@ -169,6 +175,14 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
putMappingAction.execute(request, listener);
}
@Override public ActionFuture<DeleteMappingResponse> deleteMapping(DeleteMappingRequest request) {
return deleteMappingAction.execute(request);
}
@Override public void deleteMapping(DeleteMappingRequest request, ActionListener<DeleteMappingResponse> listener) {
deleteMappingAction.execute(request, listener);
}
@Override public ActionFuture<GatewaySnapshotResponse> gatewaySnapshot(GatewaySnapshotRequest request) {
return gatewaySnapshotAction.execute(request);
}

View File

@ -25,6 +25,7 @@ import org.elasticsearch.client.action.admin.indices.create.CreateIndexRequestBu
import org.elasticsearch.client.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.client.action.admin.indices.flush.FlushRequestBuilder;
import org.elasticsearch.client.action.admin.indices.gateway.snapshot.GatewaySnapshotRequestBuilder;
import org.elasticsearch.client.action.admin.indices.mapping.delete.DeleteMappingRequestBuilder;
import org.elasticsearch.client.action.admin.indices.mapping.put.PutMappingRequestBuilder;
import org.elasticsearch.client.action.admin.indices.optimize.OptimizeRequestBuilder;
import org.elasticsearch.client.action.admin.indices.refresh.RefreshRequestBuilder;
@ -65,6 +66,10 @@ public abstract class AbstractIndicesAdminClient implements InternalIndicesAdmin
return new PutMappingRequestBuilder(this).setIndices(indices);
}
@Override public DeleteMappingRequestBuilder prepareDeleteMapping(String... indices) {
return new DeleteMappingRequestBuilder(this).setIndices(indices);
}
@Override public OptimizeRequestBuilder prepareOptimize(String... indices) {
return new OptimizeRequestBuilder(this).setIndices(indices);
}

View File

@ -34,7 +34,8 @@ import org.elasticsearch.client.transport.action.admin.indices.create.ClientTran
import org.elasticsearch.client.transport.action.admin.indices.delete.ClientTransportDeleteIndexAction;
import org.elasticsearch.client.transport.action.admin.indices.flush.ClientTransportFlushAction;
import org.elasticsearch.client.transport.action.admin.indices.gateway.snapshot.ClientTransportGatewaySnapshotAction;
import org.elasticsearch.client.transport.action.admin.indices.mapping.create.ClientTransportPutMappingAction;
import org.elasticsearch.client.transport.action.admin.indices.mapping.delete.ClientTransportDeleteMappingAction;
import org.elasticsearch.client.transport.action.admin.indices.mapping.put.ClientTransportPutMappingAction;
import org.elasticsearch.client.transport.action.admin.indices.optimize.ClientTransportOptimizeAction;
import org.elasticsearch.client.transport.action.admin.indices.refresh.ClientTransportRefreshAction;
import org.elasticsearch.client.transport.action.admin.indices.settings.ClientTransportUpdateSettingsAction;
@ -71,6 +72,7 @@ public class ClientTransportActionModule extends AbstractModule {
bind(ClientTransportCreateIndexAction.class).asEagerSingleton();
bind(ClientTransportDeleteIndexAction.class).asEagerSingleton();
bind(ClientTransportPutMappingAction.class).asEagerSingleton();
bind(ClientTransportDeleteMappingAction.class).asEagerSingleton();
bind(ClientTransportGatewaySnapshotAction.class).asEagerSingleton();
bind(ClientTransportIndicesAliasesAction.class).asEagerSingleton();
bind(ClientTransportClearIndicesCacheAction.class).asEagerSingleton();

View File

@ -0,0 +1,42 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.client.transport.action.admin.indices.mapping.delete;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingResponse;
import org.elasticsearch.client.transport.action.support.BaseClientTransportAction;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.TransportService;
/**
* @author kimchy (shay.banon)
*/
public class ClientTransportDeleteMappingAction extends BaseClientTransportAction<DeleteMappingRequest, DeleteMappingResponse> {
@Inject public ClientTransportDeleteMappingAction(Settings settings, TransportService transportService) {
super(settings, transportService, DeleteMappingResponse.class);
}
@Override protected String action() {
return TransportActions.Admin.Indices.Mapping.DELETE;
}
}

View File

@ -17,7 +17,7 @@
* under the License.
*/
package org.elasticsearch.client.transport.action.admin.indices.mapping.create;
package org.elasticsearch.client.transport.action.admin.indices.mapping.put;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;

View File

@ -34,6 +34,8 @@ import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotRequest;
import org.elasticsearch.action.admin.indices.gateway.snapshot.GatewaySnapshotResponse;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.optimize.OptimizeRequest;
@ -53,7 +55,8 @@ import org.elasticsearch.client.transport.action.admin.indices.create.ClientTran
import org.elasticsearch.client.transport.action.admin.indices.delete.ClientTransportDeleteIndexAction;
import org.elasticsearch.client.transport.action.admin.indices.flush.ClientTransportFlushAction;
import org.elasticsearch.client.transport.action.admin.indices.gateway.snapshot.ClientTransportGatewaySnapshotAction;
import org.elasticsearch.client.transport.action.admin.indices.mapping.create.ClientTransportPutMappingAction;
import org.elasticsearch.client.transport.action.admin.indices.mapping.delete.ClientTransportDeleteMappingAction;
import org.elasticsearch.client.transport.action.admin.indices.mapping.put.ClientTransportPutMappingAction;
import org.elasticsearch.client.transport.action.admin.indices.optimize.ClientTransportOptimizeAction;
import org.elasticsearch.client.transport.action.admin.indices.refresh.ClientTransportRefreshAction;
import org.elasticsearch.client.transport.action.admin.indices.settings.ClientTransportUpdateSettingsAction;
@ -86,6 +89,8 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
private final ClientTransportPutMappingAction putMappingAction;
private final ClientTransportDeleteMappingAction deleteMappingAction;
private final ClientTransportGatewaySnapshotAction gatewaySnapshotAction;
private final ClientTransportIndicesAliasesAction indicesAliasesAction;
@ -98,7 +103,7 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
ClientTransportIndicesStatusAction indicesStatusAction,
ClientTransportCreateIndexAction createIndexAction, ClientTransportDeleteIndexAction deleteIndexAction,
ClientTransportRefreshAction refreshAction, ClientTransportFlushAction flushAction, ClientTransportOptimizeAction optimizeAction,
ClientTransportPutMappingAction putMappingAction, ClientTransportGatewaySnapshotAction gatewaySnapshotAction,
ClientTransportPutMappingAction putMappingAction, ClientTransportDeleteMappingAction deleteMappingAction, ClientTransportGatewaySnapshotAction gatewaySnapshotAction,
ClientTransportIndicesAliasesAction indicesAliasesAction, ClientTransportClearIndicesCacheAction clearIndicesCacheAction,
ClientTransportUpdateSettingsAction updateSettingsAction) {
this.nodesService = nodesService;
@ -110,6 +115,7 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
this.flushAction = flushAction;
this.optimizeAction = optimizeAction;
this.putMappingAction = putMappingAction;
this.deleteMappingAction = deleteMappingAction;
this.gatewaySnapshotAction = gatewaySnapshotAction;
this.indicesAliasesAction = indicesAliasesAction;
this.clearIndicesCacheAction = clearIndicesCacheAction;
@ -239,6 +245,23 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
});
}
@Override public ActionFuture<DeleteMappingResponse> deleteMapping(final DeleteMappingRequest request) {
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<DeleteMappingResponse>>() {
@Override public ActionFuture<DeleteMappingResponse> doWithNode(DiscoveryNode node) throws ElasticSearchException {
return deleteMappingAction.execute(node, request);
}
});
}
@Override public void deleteMapping(final DeleteMappingRequest request, final ActionListener<DeleteMappingResponse> listener) {
nodesService.execute(new TransportClientNodesService.NodeCallback<Void>() {
@Override public Void doWithNode(DiscoveryNode node) throws ElasticSearchException {
deleteMappingAction.execute(node, request, listener);
return null;
}
});
}
@Override public ActionFuture<GatewaySnapshotResponse> gatewaySnapshot(final GatewaySnapshotRequest request) {
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<GatewaySnapshotResponse>>() {
@Override public ActionFuture<GatewaySnapshotResponse> doWithNode(DiscoveryNode node) throws ElasticSearchException {

View File

@ -113,7 +113,26 @@ public class MetaDataMappingService extends AbstractComponent {
});
}
public void putMapping(final Request request, final Listener userListener) {
public void removeMapping(final RemoveRequest request) {
clusterService.submitStateUpdateTask("remove-mapping [" + request.mappingType + "]", new ClusterStateUpdateTask() {
@Override public ClusterState execute(ClusterState currentState) {
if (request.indices.length == 0) {
throw new IndexMissingException(new Index("_all"));
}
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
for (String indexName : request.indices) {
if (currentState.metaData().hasIndex(indexName)) {
builder.put(newIndexMetaDataBuilder(currentState.metaData().index(indexName)).removeMapping(request.mappingType));
}
}
return ClusterState.builder().state(currentState).metaData(builder).build();
}
});
}
public void putMapping(final PutRequest request, final Listener userListener) {
clusterService.submitStateUpdateTask("put-mapping [" + request.mappingType + "]", new ClusterStateUpdateTask() {
@Override public ClusterState execute(ClusterState currentState) {
final PutMappingListener listener = new PutMappingListener(request, userListener);
@ -256,13 +275,13 @@ public class MetaDataMappingService extends AbstractComponent {
private AtomicBoolean notified = new AtomicBoolean();
private final Request request;
private final PutRequest request;
private final Listener listener;
volatile Timeout timeout;
private PutMappingListener(Request request, Listener listener) {
private PutMappingListener(PutRequest request, Listener listener) {
this.request = request;
this.listener = listener;
}
@ -293,7 +312,19 @@ public class MetaDataMappingService extends AbstractComponent {
void onFailure(Throwable t);
}
public static class Request {
public static class RemoveRequest {
final String[] indices;
final String mappingType;
public RemoveRequest(String[] indices, String mappingType) {
this.indices = indices;
this.mappingType = mappingType;
}
}
public static class PutRequest {
final String[] indices;
@ -305,18 +336,18 @@ public class MetaDataMappingService extends AbstractComponent {
TimeValue timeout = TimeValue.timeValueSeconds(10);
public Request(String[] indices, String mappingType, String mappingSource) {
public PutRequest(String[] indices, String mappingType, String mappingSource) {
this.indices = indices;
this.mappingType = mappingType;
this.mappingSource = mappingSource;
}
public Request ignoreConflicts(boolean ignoreConflicts) {
public PutRequest ignoreConflicts(boolean ignoreConflicts) {
this.ignoreConflicts = ignoreConflicts;
return this;
}
public Request timeout(TimeValue timeout) {
public PutRequest timeout(TimeValue timeout) {
this.timeout = timeout;
return this;
}

View File

@ -99,6 +99,14 @@ public class DocumentFieldMappers implements Iterable<FieldMapper> {
return fieldMappers.iterator();
}
public ImmutableList<FieldMapper> mappers() {
return this.fieldMappers;
}
public boolean hasMapper(FieldMapper fieldMapper) {
return fieldMappers.contains(fieldMapper);
}
public FieldMappers name(String name) {
return nameFieldMappers.get(name);
}

View File

@ -24,6 +24,8 @@ import org.elasticsearch.common.collect.Iterators;
import org.elasticsearch.common.collect.UnmodifiableIterator;
import org.elasticsearch.common.util.concurrent.Immutable;
import java.util.List;
/**
* A holder for several {@link FieldMapper}.
*
@ -85,4 +87,30 @@ public class FieldMappers implements Iterable<FieldMapper> {
public FieldMappers concat(FieldMappers mappers) {
return new FieldMappers(new ImmutableList.Builder<FieldMapper>().addAll(fieldMappers).addAll(mappers).build());
}
public FieldMappers remove(List<FieldMapper> mappers) {
ImmutableList.Builder<FieldMapper> builder = new ImmutableList.Builder<FieldMapper>();
for (FieldMapper fieldMapper : fieldMappers) {
boolean found = false;
for (FieldMapper mapper : mappers) {
if (fieldMapper.equals(mapper)) { // identify equality
found = true;
}
}
if (!found) {
builder.add(fieldMapper);
}
}
return new FieldMappers(builder.build());
}
public FieldMappers remove(FieldMapper mapper) {
ImmutableList.Builder<FieldMapper> builder = new ImmutableList.Builder<FieldMapper>();
for (FieldMapper fieldMapper : fieldMappers) {
if (!fieldMapper.equals(mapper)) { // identify equality
builder.add(fieldMapper);
}
}
return new FieldMappers(builder.build());
}
}

View File

@ -31,6 +31,10 @@ public class FieldMappersFieldSelector implements FieldSelector {
private final HashSet<String> names = new HashSet<String>();
public void add(String fieldName) {
names.add(fieldName);
}
public void add(FieldMappers fieldMappers) {
for (FieldMapper fieldMapper : fieldMappers) {
names.add(fieldMapper.names().indexName());

View File

@ -67,10 +67,6 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
private volatile ImmutableMap<String, FieldMappers> nameFieldMappers = ImmutableMap.of();
private volatile ImmutableMap<String, FieldMappers> indexNameFieldMappers = ImmutableMap.of();
private volatile ImmutableMap<String, FieldMappers> fullNameFieldMappers = ImmutableMap.of();
private volatile FieldMappers idFieldMappers = new FieldMappers();
private volatile FieldMappers typeFieldMappers = new FieldMappers();
private volatile FieldMappers uidFieldMappers = new FieldMappers();
private volatile FieldMappers sourceFieldMappers = new FieldMappers();
// for now, just use the xcontent one. Can work on it more to support custom ones
private final DocumentMapperParser documentParser;
@ -163,6 +159,49 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
}
}
public void remove(String type) {
synchronized (mutex) {
DocumentMapper docMapper = mappers.get(type);
if (docMapper == null) {
return;
}
mappers = newMapBuilder(mappers).remove(type).immutableMap();
// we need to remove those mappers
for (FieldMapper mapper : docMapper.mappers()) {
FieldMappers mappers = nameFieldMappers.get(mapper.names().name());
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
nameFieldMappers = newMapBuilder(nameFieldMappers).remove(mapper.names().name()).immutableMap();
} else {
nameFieldMappers = newMapBuilder(nameFieldMappers).put(mapper.names().name(), mappers).immutableMap();
}
}
mappers = indexNameFieldMappers.get(mapper.names().name());
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).remove(mapper.names().name()).immutableMap();
} else {
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).put(mapper.names().name(), mappers).immutableMap();
}
}
mappers = fullNameFieldMappers.get(mapper.names().name());
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).remove(mapper.names().name()).immutableMap();
} else {
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).put(mapper.names().name(), mappers).immutableMap();
}
}
}
}
}
/**
* Just parses and returns the mapper without adding it.
*/
@ -178,22 +217,6 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
return mappers.get(type);
}
public FieldMappers idFieldMappers() {
return this.idFieldMappers;
}
public FieldMappers typeFieldMappers() {
return this.typeFieldMappers;
}
public FieldMappers sourceFieldMappers() {
return this.sourceFieldMappers;
}
public FieldMappers uidFieldMappers() {
return this.uidFieldMappers;
}
/**
* Returns {@link FieldMappers} for all the {@link FieldMapper}s that are registered
* under the given name across all the different {@link DocumentMapper} types.
@ -411,20 +434,6 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
private class InternalFieldMapperListener implements FieldMapperListener {
@Override public void fieldMapper(FieldMapper fieldMapper) {
synchronized (mutex) {
if (fieldMapper instanceof IdFieldMapper) {
idFieldMappers = idFieldMappers.concat(fieldMapper);
}
if (fieldMapper instanceof TypeFieldMapper) {
typeFieldMappers = typeFieldMappers.concat(fieldMapper);
}
if (fieldMapper instanceof SourceFieldMapper) {
sourceFieldMappers = sourceFieldMappers.concat(fieldMapper);
}
if (fieldMapper instanceof UidFieldMapper) {
uidFieldMappers = uidFieldMappers.concat(fieldMapper);
}
FieldMappers mappers = nameFieldMappers.get(fieldMapper.names().name());
if (mappers == null) {
mappers = new FieldMappers(fieldMapper);

View File

@ -195,7 +195,7 @@ public class IndicesClusterStateService extends AbstractLifecycleComponent<Indic
IndexService indexService = indicesService.indexServiceSafe(index);
MapperService mapperService = indexService.mapperService();
ImmutableMap<String, CompressedString> mappings = indexMetaData.mappings();
// we don't support removing mappings for now ...
// go over and add the relevant mappings (or update them)
for (Map.Entry<String, CompressedString> entry : mappings.entrySet()) {
String mappingType = entry.getKey();
CompressedString mappingSource = entry.getValue();
@ -222,6 +222,13 @@ public class IndicesClusterStateService extends AbstractLifecycleComponent<Indic
logger.warn("[{}] failed to add mapping [{}], source [{}]", e, index, mappingType, mappingSource);
}
}
// go over and remove mappings
for (DocumentMapper documentMapper : mapperService) {
if (!mappings.containsKey(documentMapper.type())) {
// we have it in our mappings, but not in the metadata, remove it
mapperService.remove(documentMapper.type());
}
}
}
}

View File

@ -35,6 +35,7 @@ import org.elasticsearch.rest.action.admin.indices.create.RestCreateIndexAction;
import org.elasticsearch.rest.action.admin.indices.delete.RestDeleteIndexAction;
import org.elasticsearch.rest.action.admin.indices.flush.RestFlushAction;
import org.elasticsearch.rest.action.admin.indices.gateway.snapshot.RestGatewaySnapshotAction;
import org.elasticsearch.rest.action.admin.indices.mapping.delete.RestDeleteMappingAction;
import org.elasticsearch.rest.action.admin.indices.mapping.get.RestGetMappingAction;
import org.elasticsearch.rest.action.admin.indices.mapping.put.RestPutMappingAction;
import org.elasticsearch.rest.action.admin.indices.optimize.RestOptimizeAction;
@ -78,6 +79,7 @@ public class RestActionModule extends AbstractModule {
bind(RestUpdateSettingsAction.class).asEagerSingleton();
bind(RestPutMappingAction.class).asEagerSingleton();
bind(RestDeleteMappingAction.class).asEagerSingleton();
bind(RestGetMappingAction.class).asEagerSingleton();
bind(RestGatewaySnapshotAction.class).asEagerSingleton();

View File

@ -0,0 +1,85 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.admin.indices.mapping.delete;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.InvalidTypeNameException;
import org.elasticsearch.index.mapper.MergeMappingException;
import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestXContentBuilder;
import java.io.IOException;
import static org.elasticsearch.ExceptionsHelper.*;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.rest.RestRequest.Method.*;
import static org.elasticsearch.rest.RestResponse.Status.*;
import static org.elasticsearch.rest.action.support.RestActions.*;
/**
* @author kimchy (shay.banon)
*/
public class RestDeleteMappingAction extends BaseRestHandler {
@Inject public RestDeleteMappingAction(Settings settings, Client client, RestController controller) {
super(settings, client);
controller.registerHandler(DELETE, "/{index}/{type}/_mapping", this);
controller.registerHandler(DELETE, "/{index}/{type}/", this);
}
@Override public void handleRequest(final RestRequest request, final RestChannel channel) {
DeleteMappingRequest deleteMappingRequest = deleteMappingRequest(splitIndices(request.param("index")));
deleteMappingRequest.type(request.param("type"));
client.admin().indices().deleteMapping(deleteMappingRequest, new ActionListener<DeleteMappingResponse>() {
@Override public void onResponse(DeleteMappingResponse response) {
try {
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
builder.startObject()
.field("ok", true);
builder.endObject();
channel.sendResponse(new XContentRestResponse(request, OK, builder));
} catch (IOException e) {
onFailure(e);
}
}
@Override public void onFailure(Throwable e) {
try {
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
Throwable t = unwrapCause(e);
if (t instanceof IndexMissingException || t instanceof InvalidTypeNameException || t instanceof MergeMappingException) {
channel.sendResponse(new XContentRestResponse(request, BAD_REQUEST, builder.startObject().field("error", t.getMessage()).endObject()));
} else {
channel.sendResponse(new XContentThrowableRestResponse(request, e));
}
} catch (IOException e1) {
logger.error("Failed to send failure response", e1);
}
}
});
}
}

View File

@ -255,7 +255,7 @@ public class FetchPhase implements SearchPhase {
}
fieldSelector.add(x);
}
fieldSelector.add(context.mapperService().uidFieldMappers());
fieldSelector.add(UidFieldMapper.NAME);
return fieldSelector;
}
}

View File

@ -0,0 +1,100 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.test.integration.indices.mapping;
import org.elasticsearch.action.count.CountResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.xcontent.QueryBuilders.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (shay.banon)
*/
public class SimpleDeleteMappingTests extends AbstractNodesTests {
protected Client client1;
protected Client client2;
@BeforeMethod public void startNodes() {
startNode("node1");
startNode("node2");
client1 = getClient1();
client2 = getClient2();
createIndex();
}
protected void createIndex() {
logger.info("Creating index test");
client1.admin().indices().create(createIndexRequest("test")).actionGet();
}
@AfterMethod public void closeNodes() {
client1.close();
client2.close();
closeAllNodes();
}
protected Client getClient1() {
return client("node1");
}
protected Client getClient2() {
return client("node2");
}
@Test public void simpleDeleteMapping() throws Exception {
for (int i = 0; i < 10; i++) {
client1.prepareIndex("test", "type1", Integer.toString(i)).setSource(jsonBuilder().startObject()
.field("value", "test" + i)
.endObject()).execute().actionGet();
}
client1.admin().indices().prepareRefresh().execute().actionGet();
for (int i = 0; i < 10; i++) {
CountResponse countResponse = client1.prepareCount().setQuery(matchAllQuery()).execute().actionGet();
assertThat(countResponse.count(), equalTo(10l));
}
ClusterState clusterState = client1.admin().cluster().prepareState().execute().actionGet().state();
assertThat(clusterState.metaData().index("test").mappings().containsKey("type1"), equalTo(true));
client1.admin().indices().prepareDeleteMapping().setType("type1").execute().actionGet();
Thread.sleep(500); // for now, we don't have ack logic, so just wait
for (int i = 0; i < 10; i++) {
CountResponse countResponse = client1.prepareCount().setQuery(matchAllQuery()).execute().actionGet();
assertThat(countResponse.count(), equalTo(0l));
}
clusterState = client1.admin().cluster().prepareState().execute().actionGet().state();
assertThat(clusterState.metaData().index("test").mappings().containsKey("type1"), equalTo(false));
}
}