public void initialize(InternalAggregation.ReduceContext context) { script = context .scriptService() .executable(scriptLang, scriptString, scriptType, ScriptContext.Standard.AGGS, params); script.setNextVar("_subset_freq", subsetDfHolder); script.setNextVar("_subset_size", subsetSizeHolder); script.setNextVar("_superset_freq", supersetDfHolder); script.setNextVar("_superset_size", supersetSizeHolder); }
@Test public void testChangingVarsCrossExecution2() { Map<String, Object> vars = new HashMap<String, Object>(); Object compiledScript = se.compile("value"); ExecutableScript script = se.executable(compiledScript, vars); script.setNextVar("value", 1); Object o = script.run(); assertThat(((Number) o).intValue(), equalTo(1)); script.setNextVar("value", 2); o = script.run(); assertThat(((Number) o).intValue(), equalTo(2)); }
public ScriptHeuristic( ExecutableScript searchScript, String scriptLang, String scriptString, ScriptService.ScriptType scriptType, Map<String, Object> params) { subsetSizeHolder = new LongAccessor(); supersetSizeHolder = new LongAccessor(); subsetDfHolder = new LongAccessor(); supersetDfHolder = new LongAccessor(); this.script = searchScript; if (script != null) { script.setNextVar("_subset_freq", subsetDfHolder); script.setNextVar("_subset_size", subsetSizeHolder); script.setNextVar("_superset_freq", supersetDfHolder); script.setNextVar("_superset_size", supersetSizeHolder); } this.scriptLang = scriptLang; this.scriptString = scriptString; this.scriptType = scriptType; this.params = params; }
@Test public void testChangingVarsCrossExecution2() { Map<String, Object> vars = new HashMap<String, Object>(); Map<String, Object> ctx = new HashMap<String, Object>(); Object compiledScript = se.compile("value"); ExecutableScript script = se.executable( new CompiledScript( ScriptService.ScriptType.INLINE, "testChangingVarsCrossExecution2", "python", compiledScript), vars); script.setNextVar("value", 1); Object o = script.run(); assertThat(((Number) o).intValue(), equalTo(1)); script.setNextVar("value", 2); o = script.run(); assertThat(((Number) o).intValue(), equalTo(2)); }
private Map<String, Object> executeScript(Script script, Map<String, Object> ctx) { try { if (scriptService != null) { ExecutableScript executableScript = scriptService.executable(script, ScriptContext.Standard.UPDATE, Collections.emptyMap()); executableScript.setNextVar("ctx", ctx); executableScript.run(); // we need to unwrap the ctx... ctx = (Map<String, Object>) executableScript.unwrap(ctx); } } catch (Exception e) { throw new IllegalArgumentException("failed to execute script", e); } return ctx; }
@Override @SuppressWarnings("unchecked") public Map<String, Object> transformSourceAsMap(Map<String, Object> sourceAsMap) { try { // We use the ctx variable and the _source name to be consistent with the update api. ExecutableScript executable = scriptService.executable(script, ScriptContext.Standard.MAPPING); Map<String, Object> ctx = new HashMap<>(1); ctx.put("_source", sourceAsMap); executable.setNextVar("ctx", ctx); executable.run(); ctx = (Map<String, Object>) executable.unwrap(ctx); return (Map<String, Object>) ctx.get("_source"); } catch (Exception e) { throw new IllegalArgumentException("failed to execute script", e); } }
@Test public void testJavaScriptInnerArrayCreation() { Map<String, Object> ctx = new HashMap<String, Object>(); Map<String, Object> doc = new HashMap<String, Object>(); ctx.put("doc", doc); Object compiled = se.compile("ctx.doc.field1 = ['value1', 'value2']"); ExecutableScript script = se.executable( new CompiledScript( ScriptService.ScriptType.INLINE, "testJavaScriptInnerArrayCreation", "js", compiled), new HashMap<String, Object>()); script.setNextVar("ctx", ctx); script.run(); Map<String, Object> unwrap = (Map<String, Object>) script.unwrap(ctx); assertThat(((Map) unwrap.get("doc")).get("field1"), instanceOf(List.class)); }
protected void shardOperation( final UpdateRequest request, final ActionListener<UpdateResponse> listener, final int retryCount) throws ElasticSearchException { IndexService indexService = indicesService.indexServiceSafe(request.index()); IndexShard indexShard = indexService.shardSafe(request.shardId()); long getDate = System.currentTimeMillis(); final GetResult getResult = indexShard .getService() .get( request.type(), request.id(), new String[] { SourceFieldMapper.NAME, RoutingFieldMapper.NAME, ParentFieldMapper.NAME, TTLFieldMapper.NAME }, true); // no doc, what to do, what to do... if (!getResult.isExists()) { if (request.upsertRequest() == null) { listener.onFailure( new DocumentMissingException( new ShardId(request.index(), request.shardId()), request.type(), request.id())); return; } final IndexRequest indexRequest = request.upsertRequest(); indexRequest .index(request.index()) .type(request.type()) .id(request.id()) // it has to be a "create!" .create(true) .routing(request.routing()) .percolate(request.percolate()) .refresh(request.refresh()) .replicationType(request.replicationType()) .consistencyLevel(request.consistencyLevel()); indexRequest.operationThreaded(false); // we fetch it from the index request so we don't generate the bytes twice, its already done // in the index request final BytesReference updateSourceBytes = indexRequest.source(); indexAction.execute( indexRequest, new ActionListener<IndexResponse>() { @Override public void onResponse(IndexResponse response) { UpdateResponse update = new UpdateResponse( response.getIndex(), response.getType(), response.getId(), response.getVersion()); update.setMatches(response.getMatches()); if (request.fields() != null && request.fields().length > 0) { Tuple<XContentType, Map<String, Object>> sourceAndContent = XContentHelper.convertToMap(updateSourceBytes, true); update.setGetResult( extractGetResult( request, response.getVersion(), sourceAndContent.v2(), sourceAndContent.v1(), updateSourceBytes)); } else { update.setGetResult(null); } listener.onResponse(update); } @Override public void onFailure(Throwable e) { e = ExceptionsHelper.unwrapCause(e); if (e instanceof VersionConflictEngineException || e instanceof DocumentAlreadyExistsException) { if (retryCount < request.retryOnConflict()) { threadPool .executor(executor()) .execute( new Runnable() { @Override public void run() { shardOperation(request, listener, retryCount + 1); } }); return; } } listener.onFailure(e); } }); return; } if (getResult.internalSourceRef() == null) { // no source, we can't do nothing, through a failure... listener.onFailure( new DocumentSourceMissingException( new ShardId(request.index(), request.shardId()), request.type(), request.id())); return; } Tuple<XContentType, Map<String, Object>> sourceAndContent = XContentHelper.convertToMap(getResult.internalSourceRef(), true); String operation = null; String timestamp = null; Long ttl = null; Object fetchedTTL = null; final Map<String, Object> updatedSourceAsMap; final XContentType updateSourceContentType = sourceAndContent.v1(); String routing = getResult.getFields().containsKey(RoutingFieldMapper.NAME) ? getResult.field(RoutingFieldMapper.NAME).getValue().toString() : null; String parent = getResult.getFields().containsKey(ParentFieldMapper.NAME) ? getResult.field(ParentFieldMapper.NAME).getValue().toString() : null; if (request.script() == null && request.doc() != null) { IndexRequest indexRequest = request.doc(); updatedSourceAsMap = sourceAndContent.v2(); if (indexRequest.ttl() > 0) { ttl = indexRequest.ttl(); } timestamp = indexRequest.timestamp(); if (indexRequest.routing() != null) { routing = indexRequest.routing(); } if (indexRequest.parent() != null) { parent = indexRequest.parent(); } XContentHelper.update(updatedSourceAsMap, indexRequest.sourceAsMap()); } else { Map<String, Object> ctx = new HashMap<String, Object>(2); ctx.put("_source", sourceAndContent.v2()); try { ExecutableScript script = scriptService.executable(request.scriptLang, request.script, request.scriptParams); script.setNextVar("ctx", ctx); script.run(); // we need to unwrap the ctx... ctx = (Map<String, Object>) script.unwrap(ctx); } catch (Exception e) { throw new ElasticSearchIllegalArgumentException("failed to execute script", e); } operation = (String) ctx.get("op"); timestamp = (String) ctx.get("_timestamp"); fetchedTTL = ctx.get("_ttl"); if (fetchedTTL != null) { if (fetchedTTL instanceof Number) { ttl = ((Number) fetchedTTL).longValue(); } else { ttl = TimeValue.parseTimeValue((String) fetchedTTL, null).millis(); } } updatedSourceAsMap = (Map<String, Object>) ctx.get("_source"); } // apply script to update the source // No TTL has been given in the update script so we keep previous TTL value if there is one if (ttl == null) { ttl = getResult.getFields().containsKey(TTLFieldMapper.NAME) ? (Long) getResult.field(TTLFieldMapper.NAME).getValue() : null; if (ttl != null) { ttl = ttl - (System.currentTimeMillis() - getDate); // It is an approximation of exact TTL value, could be improved } } // TODO: external version type, does it make sense here? does not seem like it... if (operation == null || "index".equals(operation)) { final IndexRequest indexRequest = Requests.indexRequest(request.index()) .type(request.type()) .id(request.id()) .routing(routing) .parent(parent) .source(updatedSourceAsMap, updateSourceContentType) .version(getResult.getVersion()) .replicationType(request.replicationType()) .consistencyLevel(request.consistencyLevel()) .timestamp(timestamp) .ttl(ttl) .percolate(request.percolate()) .refresh(request.refresh()); indexRequest.operationThreaded(false); // we fetch it from the index request so we don't generate the bytes twice, its already done // in the index request final BytesReference updateSourceBytes = indexRequest.source(); indexAction.execute( indexRequest, new ActionListener<IndexResponse>() { @Override public void onResponse(IndexResponse response) { UpdateResponse update = new UpdateResponse( response.getIndex(), response.getType(), response.getId(), response.getVersion()); update.setMatches(response.getMatches()); update.setGetResult( extractGetResult( request, response.getVersion(), updatedSourceAsMap, updateSourceContentType, updateSourceBytes)); listener.onResponse(update); } @Override public void onFailure(Throwable e) { e = ExceptionsHelper.unwrapCause(e); if (e instanceof VersionConflictEngineException) { if (retryCount < request.retryOnConflict()) { threadPool .executor(executor()) .execute( new Runnable() { @Override public void run() { shardOperation(request, listener, retryCount + 1); } }); return; } } listener.onFailure(e); } }); } else if ("delete".equals(operation)) { DeleteRequest deleteRequest = Requests.deleteRequest(request.index()) .type(request.type()) .id(request.id()) .routing(routing) .parent(parent) .version(getResult.getVersion()) .replicationType(request.replicationType()) .consistencyLevel(request.consistencyLevel()); deleteRequest.operationThreaded(false); deleteAction.execute( deleteRequest, new ActionListener<DeleteResponse>() { @Override public void onResponse(DeleteResponse response) { UpdateResponse update = new UpdateResponse( response.getIndex(), response.getType(), response.getId(), response.getVersion()); update.setGetResult( extractGetResult( request, response.getVersion(), updatedSourceAsMap, updateSourceContentType, null)); listener.onResponse(update); } @Override public void onFailure(Throwable e) { e = ExceptionsHelper.unwrapCause(e); if (e instanceof VersionConflictEngineException) { if (retryCount < request.retryOnConflict()) { threadPool .executor(executor()) .execute( new Runnable() { @Override public void run() { shardOperation(request, listener, retryCount + 1); } }); return; } } listener.onFailure(e); } }); } else if ("none".equals(operation)) { UpdateResponse update = new UpdateResponse( getResult.getIndex(), getResult.getType(), getResult.getId(), getResult.getVersion()); update.setGetResult( extractGetResult( request, getResult.getVersion(), updatedSourceAsMap, updateSourceContentType, null)); listener.onResponse(update); } else { logger.warn( "Used update operation [{}] for script [{}], doing nothing...", operation, request.script); listener.onResponse( new UpdateResponse( getResult.getIndex(), getResult.getType(), getResult.getId(), getResult.getVersion())); } }