All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.action.index.IndexRequest Maven / Gradle / Ivy

There is a newer version: 8.15.1
Show newest version
/*
 * 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.index;

import org.apache.lucene.util.UnicodeUtil;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.ElasticSearchGenerationException;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.ElasticSearchParseException;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.WriteConsistencyLevel;
import org.elasticsearch.action.support.replication.ReplicationType;
import org.elasticsearch.action.support.replication.ShardReplicationOperationRequest;
import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.Required;
import org.elasticsearch.common.Unicode;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

import static org.elasticsearch.action.Actions.*;

/**
 * Index request to index a typed JSON document into a specific index and make it searchable. Best
 * created using {@link org.elasticsearch.client.Requests#indexRequest(String)}.
 *
 * 

The index requires the {@link #index()}, {@link #type(String)}, {@link #id(String)} and * {@link #source(byte[])} to be set. * *

The source (content to index) can be set in its bytes form using ({@link #source(byte[])}), * its string form ({@link #source(String)}) or using a {@link org.elasticsearch.common.xcontent.XContentBuilder} * ({@link #source(org.elasticsearch.common.xcontent.XContentBuilder)}). * *

If the {@link #id(String)} is not set, it will be automatically generated. * * @author kimchy (shay.banon) * @see IndexResponse * @see org.elasticsearch.client.Requests#indexRequest(String) * @see org.elasticsearch.client.Client#index(IndexRequest) */ public class IndexRequest extends ShardReplicationOperationRequest { /** * Operation type controls if the type of the index operation. */ public static enum OpType { /** * Index the source. If there an existing document with the id, it will * be replaced. */ INDEX((byte) 0), /** * Creates the resource. Simply adds it to the index, if there is an existing * document with the id, then it won't be removed. */ CREATE((byte) 1); private byte id; OpType(byte id) { this.id = id; } /** * The internal representation of the operation type. */ public byte id() { return id; } /** * Constructs the operation type from its internal representation. */ public static OpType fromId(byte id) { if (id == 0) { return INDEX; } else if (id == 1) { return CREATE; } else { throw new ElasticSearchIllegalArgumentException("No type match for [" + id + "]"); } } } private String type; private String id; @Nullable private String routing; private byte[] source; private int sourceOffset; private int sourceLength; private boolean sourceUnsafe; private boolean sourceFromBuilder; private OpType opType = OpType.INDEX; private boolean refresh = false; private XContentType contentType = Requests.INDEX_CONTENT_TYPE; public IndexRequest() { } /** * Constructs a new index request against the specific index. The {@link #type(String)}, * {@link #id(String)} and {@link #source(byte[])} must be set. */ public IndexRequest(String index) { this.index = index; } /** * Constructs a new index request against the index, type, id and using the source. * * @param index The index to index into * @param type The type to index into * @param id The id of document */ public IndexRequest(String index, String type, String id) { this.index = index; this.type = type; this.id = id; } @Override public ActionRequestValidationException validate() { ActionRequestValidationException validationException = super.validate(); if (type == null) { validationException = addValidationError("type is missing", validationException); } if (source == null) { validationException = addValidationError("source is missing", validationException); } return validationException; } /** * Before we fork on a local thread, make sure we copy over the bytes if they are unsafe */ @Override public void beforeLocalFork() { source(); } /** * Need this in case builders are used, we need to copy after adding... */ public boolean sourceFromBuilder() { return sourceFromBuilder; } /** * Sets the index the index operation will happen on. */ @Override public IndexRequest index(String index) { super.index(index); return this; } /** * Sets the content type that will be used when generating a document from user provided objects (like Map). */ public IndexRequest contentType(XContentType contentType) { this.contentType = contentType; return this; } /** * Should the listener be called on a separate thread if needed. */ @Override public IndexRequest listenerThreaded(boolean threadedListener) { super.listenerThreaded(threadedListener); return this; } /** * Controls if the operation will be executed on a separate thread when executed locally. Defaults * to true when running in embedded mode. */ @Override public IndexRequest operationThreaded(boolean threadedOperation) { super.operationThreaded(threadedOperation); return this; } /** * The type of the indexed document. */ public String type() { return type; } /** * Sets the type of the indexed document. */ @Required public IndexRequest type(String type) { this.type = type; return this; } /** * The id of the indexed document. If not set, will be automatically generated. */ public String id() { return id; } /** * Sets the id of the indexed document. If not set, will be automatically generated. */ public IndexRequest id(String id) { this.id = id; return this; } /** * Controls the shard routing of the request. Using this value to hash the shard * and not the id. */ public IndexRequest routing(String routing) { this.routing = routing; return this; } /** * Controls the shard routing of the request. Using this value to hash the shard * and not the id. */ public String routing() { return this.routing; } /** * The source of the document to index, recopied to a new array if it has an offset or unsafe. */ public byte[] source() { if (sourceUnsafe || sourceOffset > 0) { source = Arrays.copyOfRange(source, sourceOffset, sourceOffset + sourceLength); sourceOffset = 0; sourceUnsafe = false; } return source; } public byte[] unsafeSource() { return this.source; } public int unsafeSourceOffset() { return this.sourceOffset; } public int unsafeSourceLength() { return this.sourceLength; } /** * Index the Map as a {@link org.elasticsearch.client.Requests#INDEX_CONTENT_TYPE}. * * @param source The map to index */ @Required public IndexRequest source(Map source) throws ElasticSearchGenerationException { return source(source, contentType); } /** * Index the Map as the provided content type. * * @param source The map to index */ @Required public IndexRequest source(Map source, XContentType contentType) throws ElasticSearchGenerationException { try { XContentBuilder builder = XContentFactory.contentBuilder(contentType); builder.map(source); return source(builder); } catch (IOException e) { throw new ElasticSearchGenerationException("Failed to generate [" + source + "]", e); } } /** * Sets the document source to index. * *

Note, its preferable to either set it using {@link #source(org.elasticsearch.common.xcontent.XContentBuilder)} * or using the {@link #source(byte[])}. */ @Required public IndexRequest source(String source) { UnicodeUtil.UTF8Result result = Unicode.fromStringAsUtf8(source); this.source = result.result; this.sourceOffset = 0; this.sourceLength = result.length; this.sourceUnsafe = true; return this; } /** * Sets the content source to index. */ @Required public IndexRequest source(XContentBuilder sourceBuilder) { try { source = sourceBuilder.unsafeBytes(); sourceOffset = 0; sourceLength = sourceBuilder.unsafeBytesLength(); sourceUnsafe = true; this.sourceFromBuilder = true; } catch (IOException e) { throw new ElasticSearchGenerationException("Failed to generate [" + sourceBuilder + "]", e); } return this; } @Required public IndexRequest source(String field1, Object value1) { try { XContentBuilder builder = XContentFactory.contentBuilder(contentType); builder.startObject().field(field1, value1).endObject(); return source(builder); } catch (IOException e) { throw new ElasticSearchGenerationException("Failed to generate", e); } } @Required public IndexRequest source(String field1, Object value1, String field2, Object value2) { try { XContentBuilder builder = XContentFactory.contentBuilder(contentType); builder.startObject().field(field1, value1).field(field2, value2).endObject(); return source(builder); } catch (IOException e) { throw new ElasticSearchGenerationException("Failed to generate", e); } } @Required public IndexRequest source(String field1, Object value1, String field2, Object value2, String field3, Object value3) { try { XContentBuilder builder = XContentFactory.contentBuilder(contentType); builder.startObject().field(field1, value1).field(field2, value2).field(field3, value3).endObject(); return source(builder); } catch (IOException e) { throw new ElasticSearchGenerationException("Failed to generate", e); } } @Required public IndexRequest source(String field1, Object value1, String field2, Object value2, String field3, Object value3, String field4, Object value4) { try { XContentBuilder builder = XContentFactory.contentBuilder(contentType); builder.startObject().field(field1, value1).field(field2, value2).field(field3, value3).field(field4, value4).endObject(); return source(builder); } catch (IOException e) { throw new ElasticSearchGenerationException("Failed to generate", e); } } /** * Sets the document to index in bytes form. */ public IndexRequest source(byte[] source) { return source(source, 0, source.length); } /** * Sets the document to index in bytes form (assumed to be safe to be used from different * threads). * * @param source The source to index * @param offset The offset in the byte array * @param length The length of the data */ @Required public IndexRequest source(byte[] source, int offset, int length) { return source(source, offset, length, false); } /** * Sets the document to index in bytes form. * * @param source The source to index * @param offset The offset in the byte array * @param length The length of the data * @param unsafe Is the byte array safe to be used form a different thread */ @Required public IndexRequest source(byte[] source, int offset, int length, boolean unsafe) { this.source = source; this.sourceOffset = offset; this.sourceLength = length; this.sourceUnsafe = unsafe; return this; } /** * A timeout to wait if the index operation can't be performed immediately. Defaults to 1m. */ public IndexRequest timeout(TimeValue timeout) { this.timeout = timeout; return this; } /** * A timeout to wait if the index operation can't be performed immediately. Defaults to 1m. */ public IndexRequest timeout(String timeout) { return timeout(TimeValue.parseTimeValue(timeout, null)); } /** * Sets the type of operation to perform. */ public IndexRequest opType(OpType opType) { this.opType = opType; return this; } /** * Sets a string representation of the {@link #opType(org.elasticsearch.action.index.IndexRequest.OpType)}. Can * be either "index" or "create". */ public IndexRequest opType(String opType) throws ElasticSearchIllegalArgumentException { if ("create".equals(opType)) { return opType(OpType.CREATE); } else if ("index".equals(opType)) { return opType(OpType.INDEX); } else { throw new ElasticSearchIllegalArgumentException("No index opType matching [" + opType + "]"); } } /** * Set the replication type for this operation. */ @Override public IndexRequest replicationType(ReplicationType replicationType) { super.replicationType(replicationType); return this; } /** * Sets the consistency level of write. Defaults to {@link org.elasticsearch.action.WriteConsistencyLevel#DEFAULT} */ @Override public IndexRequest consistencyLevel(WriteConsistencyLevel consistencyLevel) { super.consistencyLevel(consistencyLevel); return this; } /** * Set the replication type for this operation. */ public IndexRequest replicationType(String replicationType) { super.replicationType(ReplicationType.fromString(replicationType)); return this; } /** * Set to true to force this index to use {@link OpType#CREATE}. */ public IndexRequest create(boolean create) { if (create) { return opType(OpType.CREATE); } else { return opType(OpType.INDEX); } } /** * The type of operation to perform. */ public OpType opType() { return this.opType; } /** * Should a refresh be executed post this index operation causing the operation to * be searchable. Note, heavy indexing should not set this to true. Defaults * to false. */ public IndexRequest refresh(boolean refresh) { this.refresh = refresh; return this; } public boolean refresh() { return this.refresh; } public void processRouting(MappingMetaData mappingMd) throws ElasticSearchException { if (routing == null && mappingMd.routing().hasPath()) { XContentParser parser = null; try { parser = XContentFactory.xContent(source, sourceOffset, sourceLength) .createParser(source, sourceOffset, sourceLength); routing = mappingMd.parseRouting(parser); } catch (Exception e) { throw new ElasticSearchParseException("failed to parse doc to extract routing", e); } finally { if (parser != null) { parser.close(); } } } // might as well check for routing here if (mappingMd.routing().required() && routing == null) { throw new RoutingMissingException(index, type, id); } } @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); type = in.readUTF(); if (in.readBoolean()) { id = in.readUTF(); } if (in.readBoolean()) { routing = in.readUTF(); } sourceUnsafe = false; sourceOffset = 0; sourceLength = in.readVInt(); source = new byte[sourceLength]; in.readFully(source); opType = OpType.fromId(in.readByte()); refresh = in.readBoolean(); } @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); out.writeUTF(type); if (id == null) { out.writeBoolean(false); } else { out.writeBoolean(true); out.writeUTF(id); } if (routing == null) { out.writeBoolean(false); } else { out.writeBoolean(true); out.writeUTF(routing); } out.writeVInt(sourceLength); out.writeBytes(source, sourceOffset, sourceLength); out.writeByte(opType.id()); out.writeBoolean(refresh); } @Override public String toString() { String sSource = "_na_"; try { sSource = Unicode.fromBytes(source, sourceOffset, sourceLength); } catch (Exception e) { // ignore } return "index {[" + index + "][" + type + "][" + id + "], source[" + sSource + "]}"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy