/* * Licensed to ElasticSearch and Shay Banon 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.test.integration.update; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.index.engine.DocumentMissingException; import org.elasticsearch.test.integration.AbstractNodesTests; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; public class UpdateTests extends AbstractNodesTests { private Client client; @BeforeClass public void startNodes() throws Exception { startNode("node1", nodeSettings()); startNode("node2", nodeSettings()); client = getClient(); } protected void createIndex() throws Exception { try { client.admin().indices().prepareDelete("test").execute().actionGet(); } catch (Exception e) { // ignore } logger.info("--> creating index test"); client.admin().indices().prepareCreate("test") .addMapping("type1", XContentFactory.jsonBuilder() .startObject() .startObject("type1") .startObject("_timestamp").field("enabled", true).field("store", "yes").endObject() .startObject("_ttl").field("enabled", true).field("store", "yes").endObject() .endObject() .endObject()) .execute().actionGet(); } protected Settings nodeSettings() { return ImmutableSettings.Builder.EMPTY_SETTINGS; } protected String getConcreteIndexName() { return "test"; } @AfterClass public void closeNodes() { client.close(); closeAllNodes(); } protected Client getClient() { return client("node1"); } @Test public void testUpdateRequest() throws Exception { UpdateRequest request = new UpdateRequest("test", "type", "1"); // simple script request.source(XContentFactory.jsonBuilder().startObject() .field("script", "script1") .endObject()); assertThat(request.script(), equalTo("script1")); // script with params request = new UpdateRequest("test", "type", "1"); request.source(XContentFactory.jsonBuilder().startObject() .field("script", "script1") .startObject("params").field("param1", "value1").endObject() .endObject()); assertThat(request.script(), equalTo("script1")); assertThat(request.scriptParams().get("param1").toString(), equalTo("value1")); request = new UpdateRequest("test", "type", "1"); request.source(XContentFactory.jsonBuilder().startObject() .startObject("params").field("param1", "value1").endObject() .field("script", "script1") .endObject()); assertThat(request.script(), equalTo("script1")); assertThat(request.scriptParams().get("param1").toString(), equalTo("value1")); // script with params and upsert request = new UpdateRequest("test", "type", "1"); request.source(XContentFactory.jsonBuilder().startObject() .startObject("params").field("param1", "value1").endObject() .field("script", "script1") .startObject("upsert").field("field1", "value1").startObject("compound").field("field2", "value2").endObject().endObject() .endObject()); assertThat(request.script(), equalTo("script1")); assertThat(request.scriptParams().get("param1").toString(), equalTo("value1")); Map<String, Object> upsertDoc = XContentHelper.convertToMap(request.upsertRequest().source(), true).v2(); assertThat(upsertDoc.get("field1").toString(), equalTo("value1")); assertThat(((Map) upsertDoc.get("compound")).get("field2").toString(), equalTo("value2")); request = new UpdateRequest("test", "type", "1"); request.source(XContentFactory.jsonBuilder().startObject() .startObject("upsert").field("field1", "value1").startObject("compound").field("field2", "value2").endObject().endObject() .startObject("params").field("param1", "value1").endObject() .field("script", "script1") .endObject()); assertThat(request.script(), equalTo("script1")); assertThat(request.scriptParams().get("param1").toString(), equalTo("value1")); upsertDoc = XContentHelper.convertToMap(request.upsertRequest().source(), true).v2(); assertThat(upsertDoc.get("field1").toString(), equalTo("value1")); assertThat(((Map) upsertDoc.get("compound")).get("field2").toString(), equalTo("value2")); request = new UpdateRequest("test", "type", "1"); request.source(XContentFactory.jsonBuilder().startObject() .startObject("params").field("param1", "value1").endObject() .startObject("upsert").field("field1", "value1").startObject("compound").field("field2", "value2").endObject().endObject() .field("script", "script1") .endObject()); assertThat(request.script(), equalTo("script1")); assertThat(request.scriptParams().get("param1").toString(), equalTo("value1")); upsertDoc = XContentHelper.convertToMap(request.upsertRequest().source(), true).v2(); assertThat(upsertDoc.get("field1").toString(), equalTo("value1")); assertThat(((Map) upsertDoc.get("compound")).get("field2").toString(), equalTo("value2")); // script with doc request = new UpdateRequest("test", "type", "1"); request.source(XContentFactory.jsonBuilder().startObject() .startObject("doc").field("field1", "value1").startObject("compound").field("field2", "value2").endObject().endObject() .endObject()); Map<String, Object> doc = request.doc().sourceAsMap(); assertThat(doc.get("field1").toString(), equalTo("value1")); assertThat(((Map) doc.get("compound")).get("field2").toString(), equalTo("value2")); } @Test public void testUpsert() throws Exception { createIndex(); ClusterHealthResponse clusterHealth = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet(); assertThat(clusterHealth.timedOut(), equalTo(false)); assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN)); client.prepareUpdate("test", "type1", "1") .setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject()) .setScript("ctx._source.field += 1") .execute().actionGet(); for (int i = 0; i < 5; i++) { GetResponse getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("1")); } client.prepareUpdate("test", "type1", "1") .setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject()) .setScript("ctx._source.field += 1") .execute().actionGet(); for (int i = 0; i < 5; i++) { GetResponse getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("2")); } } @Test public void testUpdate() throws Exception { createIndex(); ClusterHealthResponse clusterHealth = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet(); assertThat(clusterHealth.timedOut(), equalTo(false)); assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN)); try { client.prepareUpdate("test", "type1", "1").setScript("ctx._source.field++").execute().actionGet(); assert false; } catch (DocumentMissingException e) { // all is well } client.prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet(); UpdateResponse updateResponse = client.prepareUpdate("test", "type1", "1").setScript("ctx._source.field += 1").execute().actionGet(); assertThat(updateResponse.version(), equalTo(2L)); for (int i = 0; i < 5; i++) { GetResponse getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("2")); } updateResponse = client.prepareUpdate("test", "type1", "1").setScript("ctx._source.field += count").addScriptParam("count", 3).execute().actionGet(); assertThat(updateResponse.version(), equalTo(3L)); for (int i = 0; i < 5; i++) { GetResponse getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("5")); } // check noop updateResponse = client.prepareUpdate("test", "type1", "1").setScript("ctx.op = 'none'").execute().actionGet(); assertThat(updateResponse.version(), equalTo(3L)); for (int i = 0; i < 5; i++) { GetResponse getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("5")); } // check delete updateResponse = client.prepareUpdate("test", "type1", "1").setScript("ctx.op = 'delete'").execute().actionGet(); assertThat(updateResponse.version(), equalTo(4L)); for (int i = 0; i < 5; i++) { GetResponse getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.exists(), equalTo(false)); } // check percolation client.prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet(); logger.info("--> register a query"); client.prepareIndex("_percolator", "test", "1") .setSource(jsonBuilder().startObject() .field("query", termQuery("field", 2)) .endObject()) .setRefresh(true) .execute().actionGet(); clusterHealth = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet(); assertThat(clusterHealth.timedOut(), equalTo(false)); assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN)); updateResponse = client.prepareUpdate("test", "type1", "1").setScript("ctx._source.field += 1").setPercolate("*").execute().actionGet(); assertThat(updateResponse.matches().size(), equalTo(1)); // check TTL is kept after an update without TTL client.prepareIndex("test", "type1", "2").setSource("field", 1).setTTL(86400000L).setRefresh(true).execute().actionGet(); GetResponse getResponse = client.prepareGet("test", "type1", "2").setFields("_ttl").execute().actionGet(); long ttl = ((Number) getResponse.field("_ttl").value()).longValue(); assertThat(ttl, greaterThan(0L)); client.prepareUpdate("test", "type1", "2").setScript("ctx._source.field += 1").execute().actionGet(); getResponse = client.prepareGet("test", "type1", "2").setFields("_ttl").execute().actionGet(); ttl = ((Number) getResponse.field("_ttl").value()).longValue(); assertThat(ttl, greaterThan(0L)); // check TTL update client.prepareUpdate("test", "type1", "2").setScript("ctx._ttl = 3600000").execute().actionGet(); getResponse = client.prepareGet("test", "type1", "2").setFields("_ttl").execute().actionGet(); ttl = ((Number) getResponse.field("_ttl").value()).longValue(); assertThat(ttl, greaterThan(0L)); assertThat(ttl, lessThanOrEqualTo(3600000L)); // check timestamp update client.prepareIndex("test", "type1", "3").setSource("field", 1).setRefresh(true).execute().actionGet(); client.prepareUpdate("test", "type1", "3").setScript("ctx._timestamp = \"2009-11-15T14:12:12\"").execute().actionGet(); getResponse = client.prepareGet("test", "type1", "3").setFields("_timestamp").execute().actionGet(); long timestamp = ((Number) getResponse.field("_timestamp").value()).longValue(); assertThat(timestamp, equalTo(1258294332000L)); // check fields parameter client.prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet(); updateResponse = client.prepareUpdate("test", "type1", "1").setScript("ctx._source.field += 1").setFields("_source", "field").execute().actionGet(); assertThat(updateResponse.getResult(), notNullValue()); assertThat(updateResponse.getResult().sourceRef(), notNullValue()); assertThat(updateResponse.getResult().field("field").value(), notNullValue()); // check updates without script // add new field client.prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet(); updateResponse = client.prepareUpdate("test", "type1", "1").setDoc(XContentFactory.jsonBuilder().startObject().field("field2", 2).endObject()).execute().actionGet(); for (int i = 0; i < 5; i++) { getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("1")); assertThat(getResponse.sourceAsMap().get("field2").toString(), equalTo("2")); } // change existing field updateResponse = client.prepareUpdate("test", "type1", "1").setDoc(XContentFactory.jsonBuilder().startObject().field("field", 3).endObject()).execute().actionGet(); for (int i = 0; i < 5; i++) { getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); assertThat(getResponse.sourceAsMap().get("field").toString(), equalTo("3")); assertThat(getResponse.sourceAsMap().get("field2").toString(), equalTo("2")); } // recursive map Map<String, Object> testMap = new HashMap<String, Object>(); Map<String, Object> testMap2 = new HashMap<String, Object>(); Map<String, Object> testMap3 = new HashMap<String, Object>(); testMap3.put("commonkey", testMap); testMap3.put("map3", 5); testMap2.put("map2", 6); testMap.put("commonkey", testMap2); testMap.put("map1", 8); client.prepareIndex("test", "type1", "1").setSource("map", testMap).execute().actionGet(); updateResponse = client.prepareUpdate("test", "type1", "1").setDoc(XContentFactory.jsonBuilder().startObject().field("map", testMap3).endObject()).execute().actionGet(); for (int i = 0; i < 5; i++) { getResponse = client.prepareGet("test", "type1", "1").execute().actionGet(); Map map1 = (Map) getResponse.sourceAsMap().get("map"); assertThat(map1.size(), equalTo(3)); assertThat(map1.containsKey("map1"), equalTo(true)); assertThat(map1.containsKey("map3"), equalTo(true)); assertThat(map1.containsKey("commonkey"), equalTo(true)); Map map2 = (Map) map1.get("commonkey"); assertThat(map2.size(), equalTo(3)); assertThat(map2.containsKey("map1"), equalTo(true)); assertThat(map2.containsKey("map2"), equalTo(true)); assertThat(map2.containsKey("commonkey"), equalTo(true)); } } }