Добавление сопоставления для типа из Java - как мне это сделать?
Я пытаюсь воссоздать этот пример, используя Java API более или менее.
Я думаю, что все, что мне нужно, это добавить отображение в индекс, но в документах по Java API не совсем ясно, как это сделать.
Пожалуйста, скажите мне, как я создаю отображение в Java, которое эквивалентно этому из примера в документации:
curl -X PUT localhost:9200/test/tweet/_mapping -d '{
"tweet" : {
"_ttl" : { "enabled" : true, "default" : "1d" }
}
}'
Вот мой код:
package foo;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import java.io.IOException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
public class MyTestClass {
private static Client getClient() {
ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder();
TransportClient transportClient = new TransportClient(settings);
transportClient = transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", 9300));
return (Client) transportClient;
}
public static void main(String[] args) throws IOException, InterruptedException {
final Client client = getClient();
// Create Index and set settings and mappings
final String indexName = "test";
final String documentType = "tweet";
final String documentId = "1";
final String fieldName = "foo";
final String value = "bar";
IndicesExistsResponse res = client.admin().indices().prepareExists(indexName).execute().actionGet();
if (res.isExists()) {
DeleteIndexRequestBuilder delIdx = client.admin().indices().prepareDelete(indexName);
delIdx.execute().actionGet();
}
CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName);
// MAPPING GOES HERE
// createIndexRequestBuilder.addMapping(documentType, WHATEVER THE MAPPING IS);
// MAPPING DONE
createIndexRequestBuilder.execute().actionGet();
// Add documents
IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, documentType, documentId);
// build json object
XContentBuilder contentBuilder = jsonBuilder().startObject().prettyPrint();
contentBuilder.field(fieldName, value);
indexRequestBuilder.setSource(contentBuilder);
indexRequestBuilder.execute().actionGet();
// Get document
System.out.println(getValue(client, indexName, documentType, documentId, fieldName));
Thread.sleep(10000L);
// Try again
System.out.println(getValue(client, indexName, documentType, documentId, fieldName));
}
protected static String getValue(final Client client, final String indexName, final String documentType,
final String documentId, final String fieldName) {
GetRequestBuilder getRequestBuilder = client.prepareGet(indexName, documentType, documentId);
getRequestBuilder.setFields(new String[] { fieldName });
GetResponse response2 = getRequestBuilder.execute().actionGet();
String name = response2.getField(fieldName).getValue().toString();
return name;
}
}
4 ответа
Наконец день погуглил. Честно говоря, документы по API Java для asticsearch могут использовать несколько сквозных примеров, не говоря уже о JavaDoc...
Вот бегущий пример. У вас должен быть узел, работающий на localhost, чтобы это работало!
package foo;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import java.io.IOException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
public class MyTestClass {
private static final String ID_NOT_FOUND = "<ID NOT FOUND>";
private static Client getClient() {
final ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder();
TransportClient transportClient = new TransportClient(settings);
transportClient = transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", 9300));
return transportClient;
}
public static void main(final String[] args) throws IOException, InterruptedException {
final Client client = getClient();
// Create Index and set settings and mappings
final String indexName = "test";
final String documentType = "tweet";
final String documentId = "1";
final String fieldName = "foo";
final String value = "bar";
final IndicesExistsResponse res = client.admin().indices().prepareExists(indexName).execute().actionGet();
if (res.isExists()) {
final DeleteIndexRequestBuilder delIdx = client.admin().indices().prepareDelete(indexName);
delIdx.execute().actionGet();
}
final CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName);
// MAPPING GOES HERE
final XContentBuilder mappingBuilder = jsonBuilder().startObject().startObject(documentType)
.startObject("_ttl").field("enabled", "true").field("default", "1s").endObject().endObject()
.endObject();
System.out.println(mappingBuilder.string());
createIndexRequestBuilder.addMapping(documentType, mappingBuilder);
// MAPPING DONE
createIndexRequestBuilder.execute().actionGet();
// Add documents
final IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, documentType, documentId);
// build json object
final XContentBuilder contentBuilder = jsonBuilder().startObject().prettyPrint();
contentBuilder.field(fieldName, value);
indexRequestBuilder.setSource(contentBuilder);
indexRequestBuilder.execute().actionGet();
// Get document
System.out.println(getValue(client, indexName, documentType, documentId, fieldName));
int idx = 0;
while (true) {
Thread.sleep(10000L);
idx++;
System.out.println(idx * 10 + " seconds passed");
final String name = getValue(client, indexName, documentType, documentId, fieldName);
if (ID_NOT_FOUND.equals(name)) {
break;
} else {
// Try again
System.out.println(name);
}
}
System.out.println("Document was garbage collected");
}
protected static String getValue(final Client client, final String indexName, final String documentType,
final String documentId, final String fieldName) {
final GetRequestBuilder getRequestBuilder = client.prepareGet(indexName, documentType, documentId);
getRequestBuilder.setFields(new String[] { fieldName });
final GetResponse response2 = getRequestBuilder.execute().actionGet();
if (response2.isExists()) {
final String name = response2.getField(fieldName).getValue().toString();
return name;
} else {
return ID_NOT_FOUND;
}
}
}
Я на самом деле собираюсь добавить еще один ответ здесь, потому что, честно говоря, приведенные выше ответы дали начало моей реализации, но не ответили на фактический вопрос на 100% (обновление не только свойств корневого уровня, но и фактического поля / свойств). Мне потребовалось почти 2 дня, чтобы понять это (документация немного упрощена для ES Java API). Мой класс "Mapping" еще не на 100%, но позже к нему можно добавить больше полей ("формат" и т. Д.).
Я надеюсь, что это поможет всем, кто пытается использовать сопоставления обновлений!
ПОЛУЧИТЬ / ПОЛУЧИТЬ КАРТИНГИ
ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> indexMappings = response.getMappings();
ImmutableOpenMap<String, MappingMetaData> typeMappings = indexMappings.get(indexName);
MappingMetaData mapping = typeMappings.get(type);
Map<String, Mapping> mappingAsMap = new HashMap<>();
try {
Object properties = mapping.sourceAsMap().get("properties");
mappingAsMap = (Map<String, Mapping>) gson.fromJson(gson.toJson(properties), _elasticsearch_type_mapping_map_type);
return mappingAsMap;
}
ОБНОВЛЕНИЕ КАРТ
PutMappingRequest mappingRequest = new PutMappingRequest(indexName);
Map<String, Object> properties = new HashMap<>();
Map<String, Object> mappingsMap = (Map<String, Object>) gson.fromJson(gson.toJson(mapping), Json._obj_map_type);
properties.put("properties", mappingsMap);
mappingRequest = mappingRequest.ignoreConflicts(true).type(type).source(properties).actionGet();
Мои типы карт GSON
public static final Type _obj_map_type = new TypeToken<LinkedHashMap<String, Object>>(){}.getType();
public static final Type _elasticsearch_type_mapping_map_type = new TypeToken<LinkedHashMap<String, Mapping>>(){}.getType();
Мой картографический класс
public class Mapping {
private String type;
private String index;
private String analyzer;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public String getAnalyzer() {
return analyzer;
}
public void setAnalyzer(String analyzer) {
this.analyzer = analyzer;
}
}
Альтернативным решением будет использование функции, называемой динамическими шаблонами. Идея очень хорошо описана в этой статье http://joelabrahamsson.com/dynamic-mappings-and-dates-in-elasticsearch/
Поэтому в этом случае используется регулярное выражение, объявляющее любое поле, начинающееся с tikaprop_, типа String.
curl -XPUT "http://localhost:9200/myindex" -d'
{
"mappings": {
"_default_": {
"date_detection": true,
"dynamic_templates": [
{
"tikaprops": {
"match": "tikaprop_.*",
"match_pattern": "regex",
"mapping": {
"type": "string"
}
}
}
]
}
}
}'
или если вы предпочитаете делать это через Java API Elasticsearch
CreateIndexRequestBuilder cirb = this.client.admin().indices().prepareCreate(INDEX_NAME).addMapping("_default_", getIndexFieldMapping());
CreateIndexResponse createIndexResponse = cirb.execute().actionGet();
private String getIndexFieldMapping() {
return IOUtils.toString(getClass().getClassLoader().getResourceAsStream("elasticsearch_dynamic_templates_config.json"));
}
с beein:asticsearch_dynamic_templates_config.json:
{
"date_detection": true,
"dynamic_templates": [
{
"tikaprops": {
"match": "tikaprop_.*",
"match_pattern": "regex",
"mapping": {
"type": "string"
}
}
}
]
}
Я начал с превосходного ответа, данного Андерсом Йохансеном, и преобразовал его в Groovy (чтобы легче было читать JSON). Я делюсь с вами своим ответом.
package com.example
import groovy.json.JsonSlurper
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse
import org.elasticsearch.action.get.GetRequestBuilder
import org.elasticsearch.action.get.GetResponse
import org.elasticsearch.action.index.IndexRequestBuilder
import org.elasticsearch.client.Client
import org.elasticsearch.client.transport.TransportClient
import org.elasticsearch.common.transport.InetSocketTransportAddress
class Stackru {
Client client;
final byte[] ipAddr = [192, 168,33, 10]; // Your ElasticSearch node ip goes here
final String indexName = "classifieds";
final String documentType = "job";
public Stackru() {
client = TransportClient.builder().build()
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByAddress(ipAddr), 9300));
}
public void index(){
final IndicesExistsResponse res = client.admin().indices().prepareExists(indexName).execute().actionGet();
if (res.isExists()) {
final DeleteIndexRequestBuilder delIdx = client.admin().indices().prepareDelete(indexName);
delIdx.execute().actionGet();
}
final CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName);
// Create Mapping
def jsonSlurper = new JsonSlurper()
def mapping = jsonSlurper.parseText '''
{
"job": {
"properties": {
"company": {
"type": "string",
"analyzer": "english"
},
"desc": {
"type": "string",
"analyzer": "english"
},
"loc": {
"type": "string",
"analyzer": "english"
},
"req": {
"type": "string",
"analyzer": "english"
},
"title": {
"type": "string",
"analyzer": "english"
},
"url": {
"type": "string",
"analyzer": "english"
}
}
}
}'''
System.out.println(mapping.toString());
createIndexRequestBuilder.addMapping(documentType, mapping);
// MAPPING DONE
createIndexRequestBuilder.execute().actionGet();
// Add documents
final IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, documentType, "1");
// build json object
def jobcontent = jsonSlurper.parseText '''
{
"company": "ACME",
"title": "Groovy Developer",
"loc": "Puerto Rico",
"desc": "Codes in Groovy",
"req": "ElasticSearch, Groovy ",
"url": "http://stackru.com/questions/22071198/adding-mapping-to-a-type-from-java-how-do-i-do-it#"
}
'''
indexRequestBuilder.setSource(jobcontent);
indexRequestBuilder.execute().actionGet();
}
private String getValue2(final String indexName, final String documentType,
final String documentId, final String fieldName) {
GetRequestBuilder getRequestBuilder = client.prepareGet(indexName, documentType, documentId);
getRequestBuilder.setFields([ fieldName ] as String[]);
GetResponse response2 = getRequestBuilder.execute().actionGet();
String name = response2.getField(fieldName).getValue().toString();
return name;
}
public String getValue(final String documentId, final String fieldName){
getValue2(indexName, documentType, documentId, fieldName )
}
public void close() {
client.close()
}
public static void main (String[] Args){
Stackru so = new Stackru();
so.index();
Thread.sleep(5000L);
System.out.println(so.getValue("1", "title"));
so.close();
}
}