从 Java 添加映射到类型 - 我该怎么做?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22071198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:23:51  来源:igfitidea点击:

Adding mapping to a type from Java - how do I do it?

javaelasticsearch

提问by Anders Johansen

I am trying to recreate this exampleusing the Java API more or less.

我正在尝试或多或少地使用 Java API重新创建此示例

I think all I need is to add a mapping to the index, but the Java API docs are not exactly clear on how to do this.

我认为我需要的只是向索引添加映射,但是 Java API 文档并不清楚如何执行此操作。

Please tell me how I create a mapping in Java that is the equivalent of this from the example in the documentation:

请告诉我如何在 Java 中创建一个映射,该映射与文档中的示例等效

curl -X PUT localhost:9200/test/tweet/_mapping -d '{
    "tweet" : {
        "_ttl" : { "enabled" : true, "default" : "1d" }
    }
}'

Here's my code:

这是我的代码:

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;
    }

}

采纳答案by Anders Johansen

Finally a day of googling paid off. Frankly the Java API docs for elasticsearch could use some end-to-end examples, not to mention JavaDoc...

终于,一天的谷歌搜索得到了回报。坦率地说,elasticsearch 的 Java API 文档可以使用一些端到端示例,更不用说 JavaDoc ...

Here's a running example. You must have a node running on localhost for this to work!

这是一个运行示例。您必须在 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;
        }
    }

}

回答by shahshi15

I am actually going to add another answer here because frankly speaking, the above answers gave a start to my implementation but didn't answer the actual question 100% (updating not just the root level properties, but the ACTUAL field/properties). Took me almost 2 days to figure this out (Documentation is a bit light for ES Java APIs). My "Mapping" class is not 100% yet, but more fields could be added to it ("format" etc) later.

我实际上要在这里添加另一个答案,因为坦率地说,上述答案为我的实现提供了一个开始,但没有 100% 回答实际问题(不仅更新根级别属性,还更新 ACTUAL 字段/属性)。我花了将近 2 天的时间才弄清楚这一点(ES Java API 的文档有点少)。我的“映射”类还不是 100%,但稍后可以向其中添加更多字段(“格式”等)。

I hope this helps everyone else who is trying to use update mappings!

我希望这可以帮助其他尝试使用更新映射的人!

GET/RETRIEVE MAPPINGS

获取/检索映射

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;
                    }

UPDATE MAPPINGS

更新映射

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();

My GSON mapping types

我的 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();

My Mapping Class

我的映射类

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;
    }
}

回答by Ichwardort

An alternative solution would be to use a feature called dynamic templates. The idea is very well described within this article http://joelabrahamsson.com/dynamic-mappings-and-dates-in-elasticsearch/

另一种解决方案是使用称为动态模板的功能。这个想法在这篇文章中得到了很好的描述http://joelabrahamsson.com/dynamic-mappings-and-dates-in-elasticsearch/

So this case uses a regular expression declaring any field that starts with tikaprop_ to be of type String.

所以这个案例使用了一个正则表达式,声明任何以 tikaprop_ 开头的字段都是字符串类型。

curl -XPUT "http://localhost:9200/myindex" -d'
    {
       "mappings": {
          "_default_": {
             "date_detection": true,
             "dynamic_templates": [
                {
                   "tikaprops": {
                      "match": "tikaprop_.*",
                      "match_pattern": "regex",
                      "mapping": {
                         "type": "string"
                      }
                   }
                }
             ]
          }
       }
    }'

or if you'd rather prefer to do it via the Elasticsearch Java API

或者如果你更喜欢通过 Elasticsearch Java API 来做

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"));
}

with elasticsearch_dynamic_templates_config.json beein:

使用 elasticsearch_dynamic_templates_config.json :

{
     "date_detection": true,
     "dynamic_templates": [
        {
           "tikaprops": {
              "match": "tikaprop_.*",
              "match_pattern": "regex",
              "mapping": {
                 "type": "string"
              }
           }
        }
     ]
   }

回答by Yamir Encarnacion

I started with the excellent answer given by Anders Johansen and converted it to Groovy (so that the JSON is easier to read). I share with you my answer.

我从 Anders Johansen 给出的优秀答案开始,并将其转换为 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 StackOverflow {

    Client client;
    final byte[] ipAddr = [192, 168,33, 10]; // Your ElasticSearch node ip goes here
    final String indexName = "classifieds";
    final String documentType = "job";

    public StackOverflow() {
        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://stackoverflow.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){
        StackOverflow so =  new StackOverflow();

        so.index();
        Thread.sleep(5000L);
        System.out.println(so.getValue("1", "title"));
        so.close();
    }
}