5

I want to put mapping for a field by JAVA API but failed. Following is detailed information:

My data structure is :

{
  "mje-test-execution-id": "464b66ea6c914ddda217659c84a3cb9d",
  "jvm-free-memory": 315245608,
  "jvm-total-memory": 361758720,
  "system-free-memory": 0,
  "jvm-max-memory": 7600078848,
  "system-total-memory": 34199306240,
  "memory-time-stamp": "2020-03-12T05:12:16.835Z",
  "mje-host-name": "CN-00015345",
  "mje-test-suite-name": "SCF Test no mje version",
  "mje-version": "1.8.7771-SNAPSHOT",
  "mje-test-artifact-id": "msran-regression-tests",
  "mje-test-version": "1.8.7771-SNAPSHOT",
  "stp-id": "vran-stp",
  "mje-test-location": {
    "lat": 58.41,
    "lon": 15.62
  }
}

What I want to do is : put "mje-test-location" type to be "geo_point"

My code snippet :

public void postMapping(String indexName, String field, String type) throws IOException {
        GetIndexRequest request = new GetIndexRequest(indexName);

        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        if (!exists) {
            LOGGER.info("index {} does not exist. Now to post mapping.", indexName);
            PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
            XContentBuilder builder = XContentFactory.jsonBuilder();
            builder.startObject();
            {

                builder.startObject("properties");
                {
                    builder.startObject(field);
                    {
                        builder.field("type", type);
                    }
                    builder.endObject();
                }
                builder.endObject();
            }
            builder.endObject();
            putMappingRequest.source(builder);
            //

            AcknowledgedResponse putMappingResponse = client.indices().putMapping(putMappingRequest,
                    RequestOptions.DEFAULT);

            boolean acknowledged = putMappingResponse.isAcknowledged();
            if (acknowledged) {
                LOGGER.info("Succeed to put mapping: field:{}, type: {}", field, type);
            }
        }

        LOGGER.info("Fail to put mapping due to index {} already exist, ", indexName);
    }

Error info:

15:59:54.397 [main] DEBUG org.elasticsearch.client.RestClient - request [PUT http://seliiuapp00269.lmera.ericsson.se:9208/mje-scf-v2-20200313-post/_mapping?master_timeout=30s&timeout=30s] returned [HTTP/1.1 400 Bad Request]
org.elasticsearch.ElasticsearchStatusException: Elasticsearch exception [type=action_request_validation_exception, reason=Validation Failed: 1: mapping type is missing;]

ElasticSearch JAVA API Version : <elasticsearch.rest.high.level.client>7.0.0</elasticsearch.rest.high.level.client>

Amit
  • 30,756
  • 6
  • 57
  • 88
Little sun
  • 51
  • 2
  • 1
    If I understand, the method `postMapping()` is called for each field of your document ? – fmdaboville Mar 13 '20 at 12:13
  • yes. so do you have any ideas about this ? – Little sun Mar 17 '20 at 03:56
  • @Littlesun, why you are calling this for each field, this would cause a lot of n/w calls, instead of that you should create a mapping in one go which includes all the fields – Amit Mar 17 '20 at 05:08
  • Yep, you should write a method `postMapping(indexName)`, who handle all fields, with a json file for example or another method in : https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-put-mapping.html#_mapping_source – fmdaboville Mar 17 '20 at 12:46
  • Sorry, Maybe I am not clear. I didnt call postMapping(indexName) for each field. In fact, I call this method just one time to set field "mje-test-location" to be "geo_point" type. any better ideas ? – Little sun Mar 18 '20 at 07:26
  • @Littlesun what is your Elasticsearch version, is it 6.x? I tested your code in 7.6, it works without error. – Mincong Huang Apr 04 '20 at 18:54
  • 1
    Maybe you imported the wrong type. What is the full name of your class "PutMappingRequest": org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest or org.elasticsearch.client.indices.PutMappingRequest? You should use the second one. – Mincong Huang Apr 04 '20 at 20:11
  • The client version is 6.3 . Thanks for your sussestion and I will have a try with the second class "PutMappingRequest". – Little sun Apr 07 '20 at 05:04
  • One more question , you said having test my code , so could you tell me when you invoke the putMapping API , before the index created or after the index created ? – Little sun Apr 07 '20 at 05:06
  • @Littlesun Ah, I tested with Elasticsearch 7.6. I invoked putMapping after the index creation. You can see my test here: [StackOverflow60667649IT.java](https://github.com/mincong-h/learning-elasticsearch/blob/da421c6ef2cdf3bb363bad7b9892fe6b0b230bc3/mapping/src/test/java/io/mincong/elasticsearch/StackOverflow60667649IT.java) – Mincong Huang Apr 11 '20 at 15:49
  • I don't have much experience in ES so maybe I'm wrong. From what I understand, the [removal of mapping types](https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html) happened at ES 7. Since you're using ES6, you still need to use the legacy class `org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest` and provide the type explicitly via method `PutMappingRequest#type(String type)` – Mincong Huang Apr 11 '20 at 16:00
  • helpful for me, and thanks for you very much ^_^ – Little sun Apr 14 '20 at 02:43
  • And another question to discuss if you are interesting :builder = RestClient.builder(new HttpHost("localhost", 9200, "http")); can we create rest client with "https" to replace "http"? I see rest API source code , and it seems not . However, from elasticsearch guide, we know elastic search cluster can configure as "https" to provide service , so how to connect it with java rest api? still using "http" ?Did you try it before ? – Little sun Apr 14 '20 at 02:49

2 Answers2

1

You need to specify the document type like this:

putMappingRequest.type("_doc");

And also need to specify the types of the fields in here:

builder.field("type", type);

Like: ("type", "text") or ("type", "long"), ("type", "date") ......

You can see the datatypes in here

David Buck
  • 3,752
  • 35
  • 31
  • 35
1

I'll post @Mincong's comment as an answer because I was importing the wrong import that I found from github searchs:

What is the full name of your class "PutMappingRequest": org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest or org.elasticsearch.client.indices.PutMappingRequest? You should use the second one.

Dula
  • 1,404
  • 1
  • 14
  • 29