Я использую spring data elasticsearch, и намного проще связать код с фактическим запросом elasticsearch JSON, когда я использую аннотацию @Query, как в примерах в этой связанной ссылке:

https://www.programcreek.com/java-api-examples/index.php?api=org.springframework.data.elasticsearch.annotations.Query

Мне было интересно, есть ли способ сделать запрос по всему телу JSON через java-библиотеку elasticsearch без аннотации. И.Е. в реализации метода или что-то в этом роде. Это поможет мне разобрать выделение в ответе и т. Д.

Спасибо за любую информацию.

Разъяснение из комментариев: я использую spring-data-elasticsearch 3.0.10.RELEASE с Elasticsearch 6. Поскольку spring-data-elasticsearch, похоже, еще не поддерживает RestHighLevelClient, я использую клиент TransportClient = new PreBuiltTransportClient (elasticsearchSettings) ; подход при создании ElasticsearchTemplate: вернуть новый ElasticsearchTemplate (client ());

1
TheJeff 16 Сен 2018 в 23:14

2 ответа

Лучший ответ

Я придумал один способ сделать это, но для этого нужно создать сценарий, который живет на узле Elastic. См. Файл скрипты на основе. Он не очень гибкий, но попробуйте. Вот что надо делать.

Создайте файл с именем template_doctype.mustache и скопируйте его в $ELASTIC_HOME/config/scripts. Это сценарий, который вы можете адаптировать по мере необходимости. Перезапустите Elastic или подождите 60 секунд, чтобы он перезагрузился.

{
    "query" : {
        "match" : {
            "type" : "{{param_type}}"
        }
    }
}

Мои pom.xml зависимости:

<dependencies>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
        <version>3.0.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>5.5.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.2</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

(К вашему сведению, с помощью mvn dependency:tree я обнаружил, что ваша версия spring-data-elasticsearch неявно использует версию 5.5 библиотеки ElasticSearch, даже если вы используете ElasticSearch 6.)

Создайте фиктивный индекс:

curl -X PUT http://localhost:9200/myindex

Создайте пару документов, которые можно использовать для сопоставления, чтобы убедиться, что код работает:

curl -X POST http://localhost:9200/myindex/mydoc -d '{"title":"foobar", "type":"book"}'
curl -X POST http://localhost:9200/myindex/mydoc -d '{"title":"fun", "type":"magazine"}'

Попробуйте выполнить запрос. Этот код должен возвращать один документ:

String clusterName = "my-application";
Settings elasticsearchSettings = Settings.builder().put("cluster.name", clusterName).build();
TransportClient client = new PreBuiltTransportClient(elasticsearchSettings)
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"),9300));
Map<String, Object> template_params = new HashMap<>();

// Here is where you put parameters to your script.
template_params.put("param_type", "book");
SearchResponse sr = new SearchTemplateRequestBuilder(client)
        .setScript("template_doctype")  // this is where you specify what template to use
        .setScriptType(ScriptType.FILE)
        .setScriptParams(template_params)
        .setRequest(new SearchRequest())
        .get()
        .getResponse();

SearchHit[] results = sr.getHits().getHits();
for(SearchHit hit : results){

    String sourceAsString = hit.getSourceAsString();
    if (sourceAsString != null) {
        Gson gson = new GsonBuilder().setPrettyPrinting()
                .create();
        Map map = gson.fromJson(sourceAsString, Map.class);
        System.out.println( gson.toJson(map));
    }
}

Выход:

{
  "title": "foobar",
  "type": "book"
}
2
tom 18 Сен 2018 в 00:15

Вот еще один способ сделать это, но без транспортного клиента.

Добавьте эти зависимости в свой pom.xml:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-client</artifactId>
    <version>1.19</version>
    <scope>compile</scope>
</dependency>

Затем сделайте это:

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

Client client = new Client();
final WebResource r = client.resource("http://localhost:9200").path("/myindex/_search");
String requestJson = "{\"query\" : {\"match\" : {\"type\" : \"book\"} }}";
ClientResponse response = r.post(ClientResponse.class, requestJson);
String json = response.getEntity(String.class);

Gson gson = new GsonBuilder().setPrettyPrinting()
        .create();
Map map = gson.fromJson(json, Map.class);
System.out.println(gson.toJson(map));

// to convert to SearchResponse:
JsonXContentParser xContentParser = new JsonXContentParser(NamedXContentRegistry.EMPTY,
            new JsonFactory().createParser(json));
SearchResponse searchResponse = SearchResponse.fromXContent(xContentParser);

Вывод примера:

{
    "took": 9.0,
    "timed_out": false,
    "_shards": {
        "total": 5.0,
        "successful": 5.0,
        "failed": 0.0
    },
    "hits": {
        "total": 1.0,
        "max_score": 0.2876821,
        "hits": [
        {
            "_index": "myindex",
            "_type": "mydoc",
            "_id": "AWXp8gZjXyu6lA_2Kpi2",
            "_score": 0.2876821,
            "_source": {
                "title": "foobar",
                "type": "book"
            }
        }
        ]
    }
}
1
tom 18 Сен 2018 в 22:58