Creating Indexes with proper mapping in ES 5.0 on Java API


(RJIL) #1

I am trying to index documents in ES which is running on local usign JAVA API. Its ES 5.0 No matter what I do, I am not able to create the index and hence not able to index. Two fields : name : String data: Object Although I can index straight away data field always get indexed as String which is not correct. SO, I was trying to create the index first by using

CreateIndexResponse cir = client.admin().indices().prepareCreate("test").addMapping("test.demo",mapIndex).execute().actionGet();
Map<String,Object> mapIndex=new HashMap<String,Object>();
mapIndex.put("name.type", "text");
mapIndex.put("data.type", "object");

But everytime I am getting the exception

MapperParsingException[Failed to parse mapping [test.demo]: Root mapping definition has unsupported parameters:
Tried with only demo also.Same exception.

Any help on how do I create the proper Index with Java api and then index the object as an object.
Later on I wish to extend this to nested also but atleast simple object should first work.

Thanks.


(David Pilato) #2

test.demo is not a valid type name.

Have a look at https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-admin-indices.html#java-admin-indices-put-mapping


(RJIL) #3

Hi. I am looking for Map or XContent builder. The JSON escaped string is not a feasible solution in my case.
Can you kindly help.

Thanks.


(David Pilato) #4

But you can use also XContentBuilder in addMapping() AFAIK.


(RJIL) #5

Thanks.
I used XContentBuilder but it's not working. Here's the builder I created.

XContentBuilder xcb = jsonBuilder().startObject().startObject("properties").startObject("name").field("type","text").endObject().startObject("tile").field("type","object").endObject().endObject().endObject();


(David Pilato) #6

Can you be more specific please? What is your error?


(RJIL) #7

Hello.
The error when I use XContentBuilder is as follows:

java.lang.IllegalArgumentException: unknown setting [index.properties.name.type] please check that any required plugins are installed, or check the breaking changes documentation for removed settings

The line which is trying to create the index but not happening:

CreateIndexResponse cir = client.admin().indices().prepareCreate("test").setSource(xcb).execute().actionGet();

The addition of doc follows:

Dummy d=new Dummy("one","two-to","THREE","four");

> 	XContentBuilder xcb1 = jsonBuilder().startObject().field("name","username").field("tile",d).endObject();

System.out.println(xcb1.prettyPrint().string());
IndexResponse ir=client.prepareIndex("test", "dum")
.setSource(xcb1)
.execute()
.actionGet();


(David Pilato) #8

Is it possible to see the full code. You are obviously doing something wrong but it's hard to understand what unless you share all the details.

Here the message indicates that you are passing settings somehow to you index instead of adding mapping.

My 2 cents.


(RJIL) #9

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

import java.util.Map;

import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.SearchHit;

public class Share {

public static void main(String[] args)
{
	try
	{
	Client client=EmbeddedElasticServer.getInstance("D:\\ESIndexes1","local-test").getClient();
	
	//index Creation
	XContentBuilder xcb=jsonBuilder().startObject().startObject("properties").startObject("name").field("type","text").endObject().startObject("tile").field("type","object").endObject().endObject().endObject();	
	CreateIndexResponse cir=client.admin().indices().prepareCreate("test").setSource(xcb).execute().actionGet();
	System.out.println(cir.isAcknowledged());
	
	//Data
	Dummy d=new Dummy("one","two-to","THREE","four");
	
	XContentBuilder xcb1=jsonBuilder().startObject().field("name","username").field("tile",d).endObject();
	System.out.println(xcb1.prettyPrint().string());
	IndexResponse ir=client.prepareIndex("test", "dum")
    .setSource(xcb1)
    .execute()
    .actionGet();
	
	//Searching
	SearchResponse response = client.prepareSearch("test").execute().actionGet();
	SearchHit[] results = response.getHits().getHits();
	for (SearchHit hit : results) {
		System.out.println("------------------------------");
		Map<String,Object> result = hit.getSource(); 
		System.out.println(result);
	}
	client.close();
	
	
	}catch(Exception e)
	{
		e.printStackTrace();
	}
	
	
}

}


(David Pilato) #10

Please format your code using </> icon. It will make your post more readable.

Better using setSettings and addMapping as explained in https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-admin-indices.html#java-admin-indices-create-index

FWIW look at your json document you are sending as "source" here. It is looking like:

{
  "properties": {
    // ...
  }
}

You can't put that as index settings. It's a mapping.


(RJIL) #11

Understood one bit. I now passed it as setting. But its now giving a new error.

package com.dum.test;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

import java.util.Map;

import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.SearchHit;

public class Share {

	public static void main(String[] args) {
		try {
			Client client = EmbeddedElasticServer.getInstance("D:\\ESIndexes1",
					"local-test").getClient();

			// index Creation
			XContentBuilder xcb = jsonBuilder().startObject()
					.startObject("properties").startObject("name")
					.field("type", "text").endObject().startObject("tile")
					.field("type", "object").endObject().endObject()
					.endObject();
			CreateIndexResponse cir = client.admin().indices()
					.prepareCreate("test").addMapping("dum", xcb).execute()
					.actionGet();
			System.out.println(cir.isAcknowledged());

			// Data
			Dummy d = new Dummy("one", "two-to", "THREE", "four");

			XContentBuilder xcb1 = jsonBuilder().startObject()
					.field("name", "username").field("tile", d).endObject();
			System.out.println(xcb1.prettyPrint().string());
			IndexResponse ir = client.prepareIndex("test", "dum")
					.setSource(xcb1).execute().actionGet();

			// Searching
			SearchResponse response = client.prepareSearch("test").execute()
					.actionGet();
			SearchHit[] results = response.getHits().getHits();
			for (SearchHit hit : results) {
				System.out.println("------------------------------");
				Map<String, Object> result = hit.getSource();
				System.out.println(result);
			}
			client.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

The error which I get now

MapperParsingException[object mapping for [tile] tried to parse field [tile] as object, but found a concrete value]

I am passing an object of Dummy class for "tile". Why is it treating a concrete value.

The Dummy class

public class Dummy {
	
	private String strDummyOne;
	private String strDummyTwo;
	private String strDummyThree;
	private String strDummyFour;
	public Dummy(String strDummyOne, String strDummyTwo, String strDummyThree,
			String strDummyFour) {
		super();
		this.strDummyOne = strDummyOne;
		this.strDummyTwo = strDummyTwo;
		this.strDummyThree = strDummyThree;
		this.strDummyFour = strDummyFour;
	}
	public String getStrDummyOne() {
		return strDummyOne;
	}
	public void setStrDummyOne(String strDummyOne) {
		this.strDummyOne = strDummyOne;
	}
	public String getStrDummyTwo() {
		return strDummyTwo;
	}
	public void setStrDummyTwo(String strDummyTwo) {
		this.strDummyTwo = strDummyTwo;
	}
	public String getStrDummyThree() {
		return strDummyThree;
	}
	public void setStrDummyThree(String strDummyThree) {
		this.strDummyThree = strDummyThree;
	}
	public String getStrDummyFour() {
		return strDummyFour;
	}
	public void setStrDummyFour(String strDummyFour) {
		this.strDummyFour = strDummyFour;
	}
	
	

}

(David Pilato) #12

Probably because XContent here is simply calling toString() which ends up creating a String in your case.

Actually you can't pass objects like this in elasticsearch. You have to transform your object as XContent for example.


(RJIL) #13

Have been trying to find this .. Nothing till now. Can you please guide. I mean how do I index an object as an object and then retrieve it as an object.


(RJIL) #14

Found it and got it working eventually. But a catch is there which is not working.

Dummy d = new Dummy("one", "two-to", "THREE", "four");
			ObjectMapper mapper = new ObjectMapper();
			Map<String,Object> mmp=new LinkedHashMap<String,Object>();
			mmp.put("name", "username");
			mmp.put("tile", d);

When I get the hit, I get the tile as HashMap instead of getting it as object of Dummy class. How do I get the Dummy object back instead of HashMap.


(David Pilato) #15

You can use Jackson ObjectMapper class to write to JSON or read Objects from JSON.


(system) #16

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.