{
    "version": "https://jsonfeed.org/version/1",
    "title": "imteyazahmad.com",
    "description": "",
    "home_page_url": "https://imteyazahmad.com",
    "feed_url": "https://imteyazahmad.com/feed.json",
    "user_comment": "",
    "author": {
        "name": "Imteyaz Ahmad"
    },
    "items": [
        {
            "id": "https://imteyazahmad.com/elasticsearch-get-number-of-shards-per-node-using-java-rest-client/",
            "url": "https://imteyazahmad.com/elasticsearch-get-number-of-shards-per-node-using-java-rest-client/",
            "title": "Elasticsearch: Get Number of Shards Per Node Using Java Rest Client",
            "summary": "The number of shards per node is one of the important things&hellip;",
            "content_html": "\n  <p id=\"references\">\n    The number of shards per node is one of the important things to monitor while monitoring the health of the Elasticsearch cluster. In this post, we will see how to get it programmatically.\n  </p>\n\n    <h2 id=\"introduction\">\n      Introduction\n    </h2>\n\n  <p>\n    Elasticsearch stores documents in indices. Each index is made up of one or more <code>shards</code>. Each shard is an instance of Lucene and can be considered as a self-contained index itself with a subset of the data. There are two types of shards: <strong>primary and replica shards</strong>. Primary shards are the ones where writing happens and replica shards contribute to the data redundancy and handling search queries.&nbsp;\n  </p>\n\n  <p>\n    There is no hard limit imposed by Elasticsearch on the number of shards per node. The number of shards on a node is proportional to the amount of heap memory. If you want to check the current heap memory you can use the following command:<br>\n  </p>\n<pre class=\"line-numbers  language-java\"><code>GET _cat/nodes?v=true&h=heap.current\n</code></pre>\n\n  <p>\n    One of the&nbsp;good rules of thumb is to aim for 20 shards per GB of heap memory. So for example, if a node has 10 GB heap memory, then it should have a maximum of 200 shards. To check the shards per node we can use the shard API as shown below:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>GET _cat/shards?v=true&format=json\n// Result of the above command is as following:\n[\n  {\n    \"index\": \".apm-custom-link\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"0\",\n    \"store\": \"208b\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \"accounts\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"1000\",\n    \"store\": \"382.3kb\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \"accounts\",\n    \"shard\": \"0\",\n    \"prirep\": \"r\",\n    \"state\": \"UNASSIGNED\",\n    \"docs\": null,\n    \"store\": null,\n    \"ip\": null,\n    \"node\": null\n  },\n  {\n    \"index\": \"posts\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"1\",\n    \"store\": \"4.4kb\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \"posts\",\n    \"shard\": \"0\",\n    \"prirep\": \"r\",\n    \"state\": \"UNASSIGNED\",\n    \"docs\": null,\n    \"store\": null,\n    \"ip\": null,\n    \"node\": null\n  },\n  {\n    \"index\": \".kibana_1\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"50\",\n    \"store\": \"10.4mb\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \"accounts_test\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"5000\",\n    \"store\": \"1.7mb\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \"accounts_test\",\n    \"shard\": \"0\",\n    \"prirep\": \"r\",\n    \"state\": \"UNASSIGNED\",\n    \"docs\": null,\n    \"store\": null,\n    \"ip\": null,\n    \"node\": null\n  },\n  {\n    \"index\": \"ilm-history-2-000001\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": null,\n    \"store\": null,\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \".kibana_task_manager_1\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"6\",\n    \"store\": \"417.9kb\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \".apm-agent-configuration\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"0\",\n    \"store\": \"208b\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  },\n  {\n    \"index\": \".kibana-event-log-7.9.3-000001\",\n    \"shard\": \"0\",\n    \"prirep\": \"p\",\n    \"state\": \"STARTED\",\n    \"docs\": \"4\",\n    \"store\": \"21.6kb\",\n    \"ip\": \"172.17.0.2\",\n    \"node\": \"618c33cb6a53\"\n  }\n]\n</code></pre>\n\n  <p>\n    we can then count the number of shards per node.\n  </p>\n\n    <h2 id=\"using-high-level-rest-client-for-shards-count\">\n      Using High Level Rest Client for Shards Count\n    </h2>\n\n  <p>\n    The following code shows how we can achieve the same using the Java High Level Rest client. Please note that we are using the low level rest client here to fetch the details about the shards as I could not find support in high level client. Please have a <a href=\"https://github.com/elastic/elasticsearch/issues/27205\" target=\"_blank\">look</a> into this for the completeness of high level client.\n  </p>\n<pre class=\"line-numbers  language-java\"><code>public Map&lt;String, Integer&gt; getNumberOfShardsPerNode() {\n    try {\n      final Response response = restHighLevelClient.getLowLevelClient()\n          .performRequest(new Request(\"GET\", \"/_cat/shards?v&format=json\"));\n      final var string = EntityUtils.toString(response.getEntity());\n      final var shardDetails = new ObjectMapper()\n          .readValue(string, new TypeReference&lt;List&lt;NodeDetails&gt;&gt;() {\n          });\n      final var shardsPerNode = shardDetails.stream()\n          .filter(nodeDetails -&gt; !\"UNASSIGNED\".equalsIgnoreCase(nodeDetails.getState()))\n          .collect(Collectors.groupingBy(NodeDetails::getNode, Collectors.summingInt(value -&gt; 1)));\n      shardsPerNode.forEach((node, shards) -&gt; log.info(\"Node : {}, Shard count: {}\", node, shards));\n      return shardsPerNode;\n\n    } catch (IOException ioException) {\n      ioException.printStackTrace();\n    }\n    return Collections.emptyMap();\n  }</code></pre>\n\n  <p>\n    The above code prints number of shards per node as below:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>Node : 34_b6Yiq, Shard count: 360\nNode : as0aDaPl_, Shard count: 360\nNode : 32_wkiqAf5, Shard count: 360\n</code></pre>\n\n    <h2 id=\"conclusion\">\n      Conclusion\n    </h2>\n\n  <p>\n    In this short post, we saw how to calculate the number of shards per node in the Elasticsearch cluster. Happy learning&nbsp;😊.\n  </p>\n\n    <h2 id=\"references\">\n      References\n    </h2>\n\n  <ul>\n    <li>https://pixabay.com/illustrations/ice-shards-frozen-winter-cold-1194102/</li><li>https://www.elastic.co/guide/en/elasticsearch/reference/current/size-your-shards.html<br></li><li>https://www.elastic.co/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster<br></li><li>https://github.com/elastic/elasticsearch/issues/27205<br></li>\n  </ul>",
            "image": "https://imteyazahmad.com/media/posts/9/ice-1194102_1920.jpg",
            "author": {
                "name": "Imteyaz Ahmad"
            },
            "tags": [
                   "high level rest client",
                   "Java",
                   "Elasticsearch"
            ],
            "date_published": "2021-04-26T11:37:32-04:00",
            "date_modified": "2021-05-07T10:18:18-04:00"
        },
        {
            "id": "https://imteyazahmad.com/elasticsearch-get-document-counts-using-java-high-level-rest-client/",
            "url": "https://imteyazahmad.com/elasticsearch-get-document-counts-using-java-high-level-rest-client/",
            "title": "Elasticsearch: Get Document Counts using Java High Level Rest Client",
            "summary": "We can use&nbsp;Java High Level Rest Client to get the count of&hellip;",
            "content_html": "\n  <p>\n    We can use&nbsp;Java High Level Rest Client to get the count of documents in an index. It can also be used to execute a query and get the count of matching documents.\n  </p>\n\n    <h2 id=\"introduction\">\n      Introduction\n    </h2>\n\n  <p>\n    The Elasticsearch Java High Level Rest Client provides <code>count API</code> which can be used to get the followings:\n  </p>\n\n  <ul>\n    <li>Total number of documents in the indices or</li><li>Number of documents matching a query.</li>\n  </ul>\n\n    <h2 id=\"query-building\">\n      Query Building\n    </h2>\n\n  <p>\n    In our previous <a href=\"https://imteyazahmad.com/elasticsearch-bulk-insert-using-java-high-level-rest-client/\" class=\"\">post</a> we used account data and inserted in <code>accounts</code> index. I want to know the number of documents where the first name of the account holder is&nbsp;<mark>Kelley</mark>. The following code shows the <code>JSON</code> query for the same:\n  </p>\n<pre class=\"line-numbers  language-bash\"><code>#Number of accounts with Firstname as Kelley\nPOST accounts/_count\n{\"query\":{\"match\":{\"firstname.keyword\":\"Kelley\"}}}\n</code></pre>\n\n  <p>\n    For achieving the same using Java High Level Rest Client, we can build the query as shown below:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>final var countRequest = new CountRequest(\"accounts\");\ncountRequest.query(QueryBuilders.matchQuery(\"firstname.keyword\", \"Kelley\")); \n</code></pre>\n\n    <h2 id=\"query-execution\">\n      Query Execution\n    </h2>\n\n  <p>\n    After this we can use High Level Rest Client to execute the query as following. For configuring the client please follow <a href=\"https://imteyazahmad.com/configuring-elasticsearch-java-high-level-rest-client-2/\">this post</a>.\n  </p>\n<pre class=\"line-numbers  language-java\"><code>final var countResponse = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);\nfinal var count = countResponse.getCount(); </code></pre>\n\n  <p>\n    A working code example is present in this <a href=\"https://github.com/ahmadimt/elasticsearch_samples/tree/main/count_high_level_rest_client\">git repository.</a> I hope it is useful for you. Happy learning :).\n  </p>\n\n    <h2 id=\"references\">\n      References\n    </h2>\n\n  <ul>\n    <li>https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.12/java-rest-high-count.html<br></li><li><span style=\"color: var(--eb-text-primary-color); font-family: var(--font-base); font-size: 1em; font-weight: var(--font-weight-normal);\">https://pixabay.com/vectors/hand-counting-fingers-one-two-162127/</span><br></li>\n  </ul>\n\n  <p>\n    \n  </p>",
            "image": "https://imteyazahmad.com/media/posts/8/hand-162127.png",
            "author": {
                "name": "Imteyaz Ahmad"
            },
            "tags": [
                   "high level rest client",
                   "Java",
                   "Elasticsearch"
            ],
            "date_published": "2021-04-22T10:44:36-04:00",
            "date_modified": "2021-04-22T12:12:08-04:00"
        },
        {
            "id": "https://imteyazahmad.com/elasticsearch-pre-indexing-transformation-using-ingest-pipelines/",
            "url": "https://imteyazahmad.com/elasticsearch-pre-indexing-transformation-using-ingest-pipelines/",
            "title": "Elasticsearch: A Short Introduction to Ingest Pipelines",
            "summary": "While indexing data we need to apply some changes that are common&hellip;",
            "content_html": "\n  <p id=\"introduction\">\n    While indexing data we need to apply some changes that are common to all the documents. We can achieve that with some custom logic while indexing the documents. However, that can take more efforts and can be error prone. Elasticsearch also provide an inbuilt functionality called <code>Ingest Pipelines</code> to achieve some of the transformation.\n  </p>\n\n    <h2 id=\"introduction\">\n      Introduction\n    </h2>\n\n  <p>\n    Ingest pipelines provide mean to apply some common transformations before indexing the document. e.g If we want to set a field called&nbsp;<code>writeTime</code> in each of the document or converting a field to uppercase.\n  </p>\n\n    <h3 id=\"prerequisite\">\n      Prerequisite\n    </h3>\n\n  <p>\n    The minimum requirement to use ingest pipeline is at least one of the nodes in the cluster must be an <a href=\"https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html\" target=\"_blank\"><code>ingest</code></a> node. For more details please follow <a href=\"https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html#ingest-prerequisites\" target=\"_blank\" rel=\"nofollow noopener\">this</a>.\n  </p>\n\n    <h2 id=\"ingest-pipeline-structure\">\n      Ingest Pipeline Structure\n    </h2>\n\n  <p>\n    The following block shows the structure of an ingest pipeline. The description is optional and then we can define a list of one or more <code>processors</code>. A&nbsp;processor is configurable task.&nbsp;\n  </p>\n<pre class=\"line-numbers  language-json\"><code>{\n  \"description\" : \"This is optional\",\n  \"processors\": [\n    {\n      //processor 1\n    },\n    {\n     //processor 2\n    }\n    //\n  ]\n}\n</code></pre>\n\n  <p>\n    These processors run sequentially.&nbsp;\n  </p>\n\n    <h2 id=\"use-case\">\n      Use case\n    </h2>\n\n  <p>\n    We need to add a field called <code>writeTime</code> in each document of an index in the Elasticsearch. The following pipeline achieves the same:\n  </p>\n<pre class=\"line-numbers  language-json\"><code>PUT _ingest/pipeline/write_time_pipeline\n{\n  \"description\": \"Pipeline to add writeTime in the documents\",\n  \"processors\": [\n    {\n      \"set\": {\n        \"field\": \"writeTime\",\n        \"value\": \"{{_ingest.timestamp}}\"\n      }\n    }\n}\n</code></pre>\n\n  <p>\n    Once this is done we can use this pipeline in index request as shown below:\n  </p>\n<pre class=\"line-numbers  language-json\"><code>POST my-events/_doc?pipeline=write_time_pipeline\n{\n  \"reason\": \"foo\"\n}</code></pre>\n\n  <p>\n    If you are using Java High Level Rest Client then we can use as following:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>final Map&lt;Sring, Object&gt; source = new HashMap&lt;&gt;();\nsource.put(\"reason\",\"foo\")\nIndexRequest indexRequest = new IndexRequest(\"my-events\");\n// we are setting the pipeline here to the request\nindexRequest.setPipeline(\"write_time_pipeline\");\nindexRequest.source(source);\nrestHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);\n</code></pre>\n\n  <p>\n    Elasticsearch provides a lot of processors.To get a list of available processors we can use node info API as shown below or a detailed list can be found <a href=\"https://www.elastic.co/guide/en/elasticsearch/reference/master/processors.html\" target=\"_blank\" rel=\"nofollow noopener\">here</a>.\n  </p>\n<pre class=\"line-numbers  language-bash\"><code>curl -X GET \"localhost:9200/_nodes/ingest?filter_path=nodes.*.ingest.processors&pretty\"\n</code></pre>\n\n  <p>\n    I hope this is helpful. If you have any feedback, please feel free to comment.\n  </p>\n\n    <h2 id=\"references\">\n      References\n    </h2>\n\n  <ul>\n    <li>https://pixabay.com/illustrations/digitization-transformation-binary-5140055/</li><li>https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html<br></li><li>https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html<br></li><li>https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html#ingest-prerequisites<br></li><li>https://www.elastic.co/guide/en/elasticsearch/reference/master/put-pipeline-api.html<br></li><li>https://www.elastic.co/guide/en/elasticsearch/reference/master/processors.html<br></li>\n  </ul>\n\n  <p>\n    \n  </p>",
            "image": "https://imteyazahmad.com/media/posts/7/digitization-5140055_1920.jpg",
            "author": {
                "name": "Imteyaz Ahmad"
            },
            "tags": [
                   "ingest pipeline",
                   "Java",
                   "Elasticsearch"
            ],
            "date_published": "2021-04-12T09:59:49-04:00",
            "date_modified": "2021-04-12T10:03:34-04:00"
        },
        {
            "id": "https://imteyazahmad.com/elasticsearch-bulk-insert-using-java-high-level-rest-client/",
            "url": "https://imteyazahmad.com/elasticsearch-bulk-insert-using-java-high-level-rest-client/",
            "title": "Elasticsearch: Bulk Insert using Java High Level Rest Client",
            "summary": "In our previous post, we saw how to insert data into Elasticsearch&hellip;",
            "content_html": "\n  <p id=\"introduction\">\n    In our <a href=\"https://imteyazahmad.com/elasticsearch-searching-using-java-high-level-rest-client/\" target=\"_blank\">previous post</a>, we saw how to insert data into Elasticsearch using the&nbsp;<code>curl</code> command. In this post, we will use Java High Level Rest Client to achieve the same.\n  </p>\n\n    <h2 id=\"introduction\">\n      Introduction\n    </h2>\n\n  <p>\n    For any use case, data is essential. If we already have some data in&nbsp;Elasticsearch, we can use it. Otherwise, we will have to insert some data into it. In this post, we will see how to bulk insert data using Java High Level Rest Client. The details about instantiating and configuring&nbsp;the client can be found <a href=\"https://imteyazahmad.com/configuring-elasticsearch-java-high-level-rest-client-2/\" target=\"_blank\">here</a>.\n  </p>\n\n    <h2 id=\"data-preparation\">\n      Data Preparation\n    </h2>\n\n  <p>\n    We will use the accounts data present <a href=\"https://github.com/ahmadimt/elasticsearch_samples/blob/main/bulk_insert/app/src/main/resources/accounts.json\" target=\"_blank\" rel=\"nofollow noopener\" class=\"\">here</a>. The following represents a single document in the <code>accounts</code> index in Elasticsearch:\n  </p>\n<pre class=\"line-numbers  language-json\"><code>{\"account_number\":1,\"balance\":39225,\"firstname\":\"Amber\",\"lastname\":\"Duke\",\"age\":32,\"gender\":\"M\",\"address\":\"880 Holmes Lane\",\"employer\":\"Pyrami\",\"email\":\"amberduke@pyrami.com\",\"city\":\"Brogan\",\"state\":\"IL\"}</code></pre>\n\n    <h2 id=\"writing-datanbsp\">\n      Writing Data&nbsp;\n    </h2>\n\n  <p>\n    Let's create an <code>Account</code> class that represents a single document as shown above in the index.&nbsp;\n  </p>\n<pre class=\"line-numbers  language-java\"><code>public class Account {     \nprivate static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();   \n@JsonProperty(\"account_number\")\nprivate long accountNumber;\n@JsonProperty(\"balance\")\nprivate long balance;\n@JsonProperty(\"firstname\")\nprivate String firstname;\n@JsonProperty(\"lastname\")\nprivate String lastname;\n@JsonProperty(\"age\")\nprivate int age;\n@JsonProperty(\"gender\")\nprivate String gender;\n@JsonProperty(\"address\")\nprivate String address;\n@JsonProperty(\"employer\")\nprivate String employer;\n@JsonProperty(\"email\")\nprivate String email;\n@JsonProperty(\"city\")\nprivate String city;\n@JsonProperty(\"state\")\nprivate String state;\n//Getter and Setter removed for brevity\n\n// This method is used to convert an instance of Account class to map. \n// This is done because IndexRequest accepts a map as a source.\npublic static Map&lt;String, Object&gt; getAsMap(final Account account) {\n  return OBJECT_MAPPER.convertValue(account, new TypeReference&lt;Map&lt;String, Object&gt;&gt;() {\n      });\n  }  \n}\n\n</code></pre>\n\n  <p>\n    We have one another class called <code>AccountManager</code> which reads the data from the file and writes into the Elasticsearch index:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>/**\n * The type Account manager.\n */\npublic class AccountManager {\n\n  private final RestHighLevelClient restHighLevelClient;\n\n  /**\n   *     Instantiates a new Account manager.\n   *\n   * @param restHighLevelClient the rest high level client\n   */\n  public AccountManager(final RestHighLevelClient restHighLevelClient) {\n    this.restHighLevelClient = restHighLevelClient;\n  }\n\n  /**\n   * Read data from the file and return as a List&lt;Account&gt;.\n   *\n   * @param fileName the file name\n   * @return the list\n   * @throws IOException the io exception\n   */\n  public List&lt;Account&gt; readAccounts(String fileName) throws IOException {\n    final File file = new File(fileName);\n    final Account[] accounts = new ObjectMapper().readValue(file, Account[].class);\n    return Arrays.asList(accounts);\n  }\n\n  /**\n   * Write accounts data into Elasticsearch\n   *\n   * @param accounts  the accounts\n   * @param indexName the index name\n   * @return the bulk response\n   * @throws IOException the io exception\n   */\n  public BulkResponse writeAccounts(List&lt;Account&gt; accounts, String indexName) throws IOException {\n    final var bulkRequest = new BulkRequest();\n    accounts.forEach(account -&gt; {\n      final var indexRequest = new IndexRequest(indexName);\n      indexRequest.source(Account.getAsMap(account));\n      bulkRequest.add(indexRequest);\n    });\n    return restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);\n  }\n}\n</code></pre>\n\n  <p>\n    The important thing to notice here is how we are creating the <code>BulkRequest</code> (Line#39-44). For each <code>Account</code> in the list, we are creating a new <code>IndexRequest</code> with the given index name and then passing the current account data as a map to it, which is then added to the instance of bulk request.\n  </p>\n\n  <p>\n    Once the bulk request is prepared we are calling&nbsp;<code>restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT)</code> to insert data into Elasticsearch.\n  </p>\n\n    <h2 id=\"testingnbsp\">\n      Testing&nbsp;\n    </h2>\n\n  <p>\n    The following is a test to write data into Elasticsearch:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>  @Test\n  public void writeAccountsValidAccountAndIndexNameShouldReturnBulkResponse() throws IOException {\n    final URL resource = AccountManager.class.getClassLoader()\n        .getResource(\"accounts.json\");\n    Assertions.assertThat(resource).isNotNull();\n    final List&lt;Account&gt; accounts = accountManager.readAccounts(resource.getFile());\n    final var bulkItemResponses = accountManager.writeAccounts(accounts, \"accounts_test\");\n    Assertions.assertThat(bulkItemResponses.hasFailures()).isFalse();\n    Assertions.assertThat(bulkItemResponses).isNotEmpty().hasSize(1000);\n  }</code></pre>\n\n    <h2 id=\"references\">\n      References\n    </h2>\n\n  <ul>\n    <li>https://pixabay.com/photos/dance-schools-mosquitoes-mass-1837658/?download</li><li>https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json<br></li><li>https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high.html<br></li>\n  </ul>",
            "image": "https://imteyazahmad.com/media/posts/6/dance-schools-1837658_cropped-2.jpg",
            "author": {
                "name": "Imteyaz Ahmad"
            },
            "tags": [
                   "high level rest client",
                   "Java",
                   "Elasticsearch"
            ],
            "date_published": "2021-04-10T00:16:10-04:00",
            "date_modified": "2021-04-15T10:39:38-04:00"
        },
        {
            "id": "https://imteyazahmad.com/elasticsearch-searching-using-java-high-level-rest-client/",
            "url": "https://imteyazahmad.com/elasticsearch-searching-using-java-high-level-rest-client/",
            "title": "Elasticsearch: Query using Java High Level Rest Client",
            "summary": "In the previous post we saw how to configure Elasticsearch Java high&hellip;",
            "content_html": "\n  <p>\n    In the <a href=\"https://imteyazahmad.com/configuring-elasticsearch-java-high-level-rest-client-2/\">previous post</a> we saw how to configure Elasticsearch Java high level rest client. In this post we are going to discuss how to make search request using the same.\n  </p>\n\n    <h2 id=\"introduction\">\n      Introduction\n    </h2>\n\n  <p>\n    Once we have configured our Elasticsearch Java high level rest client, it won't be useful if we don't make it work. Here we are going to use it to make some queries and see the result. We will use some fake data here.\n  </p>\n\n    <h5 id=\"adding-data\">\n      Adding Data\n    </h5>\n\n  <p>\n    We can download data from <a href=\"https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json\" target=\"_blank\" rel=\"nofollow noopener\">Elasticsearch repository</a>. If you are using Linux the we can download the data as shown&nbsp; below:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>wget https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json?raw=true -O accounts.json     \n</code></pre>\n\n  <p>\n    Once downloaded, run the below commands to insert data into Elasticsearch&nbsp;\n  </p>\n<pre class=\"line-numbers  language-bash\"><code># Create an index named \"accounts\"\ncurl XPUT http://localhost:9200/accounts\n# Bulk insert data into this index\ncurl -s -H \"Content-Type: application/x-ndjson\" -XPOST http://localhost:9200/accounts/_bulk --data-binary @accounts.json\n# once this is done we can verify the data\ncurl -XGET http://localhost:9200/accounts/_count\n#this should return something like this  \n{\"count\":1000,\"_shards\":{\"total\":1,\"successful\":1,\"skipped\":0,\"failed\":0}}\n</code></pre>\n\n    <h2 id=\"query-preparation-and-execution\">\n      Query Preparation and Execution\n    </h2>\n\n  <p>\n    With the data in place we want to know the followings:\n  </p>\n\n  <ul>\n    <li>How many users have balance between 1000-2000?</li>\n  </ul>\n\n  <p>\n    First let's see the JSON query for the same:\n  </p>\n<pre class=\"line-numbers  language-json\"><code>POST accounts/_search\n{\"size\":10000,\"query\":{\"bool\":{\"filter\":[{\"range\":{\"balance\":{\"gte\":1000,\"lte\":2000}}}]}},\"sort\":[{\"balance\":{\"order\":\"desc\"}}]}</code></pre>\n\n  <p>\n    Now, we will create the same query using Elasticsearch high level rest client.\n  </p>\n<pre class=\"line-numbers  language-java\"><code>//First we need a bool query with a range filter\nfinal var boolQueryBuilder = QueryBuilders.boolQuery();\n    boolQueryBuilder\n        .filter(QueryBuilders.rangeQuery(\"balance\")\n                .gte(1000).lte(2000)\n                .includeLower(true)\n                .includeUpper(false));\n\n//After this we provide this to SearchSourceBuilder\nfinal var searchSourceBuilder = new SearchSourceBuilder();\nsearchSourceBuilder.size(1000);\nsearchSourceBuilder.query(boolQueryBuilder);\nsearchSourceBuilder.sort(\"balance\");\n\n//And pass this source  builder to search request\nfinal var searchRequest = new SearchRequest();\nsearchRequest.indices(\"accounts\");\nsearchRequest.source(searchSourceBuilder);\n\n</code></pre>\n\n  <p>\n    Once that's done, we need to use the <code>HighLevelRestClient</code> to call Elasticsearch\n  </p>\n<pre class=\"line-numbers  language-json\"><code>final ElasticsearchConfig elasticsearchConfig = new ElasticsearchConfig();\nfinal RestHighLevelClient restHighLevelClient = elasticsearchConfig.restHighLevelClient();\nfinal var searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);\n</code></pre>\n\n  <p>\n    After this we can parse the result as shown below:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>final var hits = searchResponse.getHits().getHits();\nfinal var customers = Arrays.stream(hits)\n        .map(SearchHit::getSourceAsMap)\n        // Here we are mapping the data to string. you can also map to some object like Account\n        .map(stringObjectMap -&gt; \"Name: \" + stringObjectMap.get(\"firstname\") + \" \"\n            + stringObjectMap.get(\"lastname\") + \", Balance: \" + stringObjectMap.get(\"balance\"))\n        .collect(Collectors.toList());</code></pre>\n\n  <p>\n    A working code example is present in this <a href=\"https://github.com/ahmadimt/elasticsearch_samples/tree/main/query_high_level_rest_client\" target=\"_blank\">git repository</a>.\n  </p>\n\n    <h2 id=\"references\">\n      References\n    </h2>\n\n  <ul>\n    <li>https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json</li><li>https://pixabay.com/users/geralt-9301/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1248053</li><li>https://qbox.io/blog/understanding-bulk-indexing-in-elasticsearch/<br></li><li>https://pixabay.com/illustrations/hand-magnifying-glass-earth-globe-1248053/<br></li>\n  </ul>\n\n  <p>\n    \n  </p>\n\n  <p>\n    \n  </p>\n\n  <p>\n    \n  </p>",
            "image": "https://imteyazahmad.com/media/posts/4/hand-1248053_1920-2.jpg",
            "author": {
                "name": "Imteyaz Ahmad"
            },
            "tags": [
                   "high level rest client",
                   "Java",
                   "Elasticsearch",
                   "Analytics"
            ],
            "date_published": "2021-04-07T00:33:32-04:00",
            "date_modified": "2021-04-15T10:40:27-04:00"
        },
        {
            "id": "https://imteyazahmad.com/configuring-elasticsearch-java-high-level-rest-client-2/",
            "url": "https://imteyazahmad.com/configuring-elasticsearch-java-high-level-rest-client-2/",
            "title": "Elasticsearch: Java High Level Rest Client",
            "summary": "This article describe how to configure the new Elasticsearch Java High level&hellip;",
            "content_html": "\n  <p>\n    This article describe how to configure the new Elasticsearch Java High level rest client in a Java Application.\n  </p>\n\n    <h2 id=\"introduction\">\n      Introduction\n    </h2>\n\n  <p>\n    Elasticsearch&nbsp;5.0.0 released it first&nbsp;Java REST Client. This client was called low-level client as the Java users had to build the JSON request and parse the results. Later, Elasticsearch 5.6 introduced&nbsp;&nbsp;Java High Level REST Client which accepts&nbsp;request objects and returns response objects for the most important APIs(info, get, index, delete, update, bulk, search, search-scroll, and clear-scroll). For other APIs, we still have to use the low-level client.\n  </p>\n\n    <h2 id=\"dependencies\">\n      Dependencies\n    </h2>\n\n  <p>\n    It depends of the following artifacts and their transitive dependencies:<br>\n  </p>\n\n  <ul>\n    <li>org.elasticsearch.client:elasticsearch-rest-client</li><li>org.elasticsearch:elasticsearch<br></li>\n  </ul>\n\n  <p>\n    The minimum Java version required is <code>1.8</code>.&nbsp;\n  </p>\n\n  <p>\n    If you are using maven then it can declared as follows\n  </p>\n<pre class=\"line-numbers  language-java\"><code>&lt;dependency&gt;\n    &lt;groupId&gt;org.elasticsearch.client&lt;/groupId&gt;\n    &lt;artifactId&gt;elasticsearch-rest-high-level-client&lt;/artifactId&gt;\n    &lt;version&gt;${elasticsearch.version}&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n\n  <p>\n    The Gradle users can declare the dependencies as\n  </p>\n<pre class=\"line-numbers  language-java\"><code>dependencies {\n    compile \"org.elasticsearch.client:elasticsearch-rest-high-level-client:${elasticsearch.version}\"\n}  </code></pre>\n\n  <p>\n    Replace the <code>${elasticsearch.version}</code> as appropriate.\n  </p>\n\n    <h2 id=\"initialization\">\n      Initialization\n    </h2>\n\n  <p>\n    The <code>RestHighLevelClient</code> is built on top of the REST low-level client builder. The following code will instantiate a low level <code>RestClientBuilder</code>.\n  </p>\n<pre class=\"line-numbers  language-java\"><code>RestClientBuilder  restClientBuilder  = RestClient.builder(\n    new HttpHost(\"localhost\", 9200, \"http\"),\n    new HttpHost(\"localhost\", 9201, \"http\"));</code></pre>\n\n  <p>\n    If the Elasticsearch is secured with user name and password then we need to provide the credentials using the&nbsp;<code>CredentialsProvider</code> as shown below. After that we can set a callback that allows to modify the http client configuration.&nbsp;\n  </p>\n<pre class=\"line-numbers  language-java\"><code>final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();\ncredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(\n        &lt;elasticSearchUsername&gt;, &lt;elasticSearchPassword&gt;));\nrestClientBuilder.setHttpClientConfigCallback(new HttpClientConfigCallback() {\n      @Override\n      public HttpAsyncClientBuilder customizeHttpClient(\n          HttpAsyncClientBuilder httpClientBuilder) {\n        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);\n      }\n    });\n/*\nUsing the Java 8 syntax, we can replace the above code like this\nbuilder.setHttpClientConfigCallback(\n        httpClientBuilder -&gt; httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));\n*/</code></pre>\n\n  <p>\n    After this we can initialize the&nbsp;<code>RestHighLevelClient</code> as follows\n  </p>\n<pre class=\"line-numbers  language-java\"><code>RestHighLevelClient client = new RestHighLevelClient(restClientBuilder);</code></pre>\n\n    <h2 id=\"usage\">\n      Usage\n    </h2>\n\n  <p>\n    Each APIs in High Level REST Client can be called synchronously or asynchronously. In case of synchronous call it returns a response object. It can throw an <code>IOException</code> if either of the following occurs:\n  </p>\n\n  <ul>\n    <li>The request times out.</li><li>The client fails to parse the REST response</li><li>There is no response coming back from the server<br></li>\n  </ul>\n<pre class=\"line-numbers  language-java\"><code>SearchRequest searchRequest = new SearchRequest(\"posts\");\nsearchRequest.source(searchSourceBuilder);\nSearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);  \n</code></pre>\n\n  <p>\n    The following shows how to call a method asynchronously. We need to define an <code>ActionListener</code> which define how to handle the response and error if any. The following shows the code example for that:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>// Asynchronous call example\nActionListener&lt;SearchResponse&gt; listener = new ActionListener&lt;SearchResponse&gt;() {\n    @Override\n    public void onResponse(SearchResponse searchResponse) {\n         //write the logic to parse the search response. \n    }\n\n    @Override\n    public void onFailure(Exception e) {\n        //Code to handle the exception goes here.\n    }\n};\nclient.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);\n\n</code></pre>\n\n  <p>\n    Once we are done with the processing, the client can closed as follows:\n  </p>\n<pre class=\"line-numbers  language-java\"><code>client.close();</code></pre>\n\n  <p>\n    A working code example is present in <a href=\"https://github.com/ahmadimt/elasticsearch_samples/tree/main/high_level_rest_client\" target=\"_blank\">this git repository</a>.\n  </p>\n\n    <h2 id=\"references\">\n      References\n    </h2>\n\n  <ul>\n    <li>https://github.com/ahmadimt/elasticsearch_samples/tree/main/high_level_rest_client<br></li><li>https://www.elastic.co/blog/state-of-the-official-elasticsearch-java-clients</li><li>https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high.html<br></li><li>https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-low.html<br></li><li>https://pixabay.com/illustrations/ball-round-cable-lan-connected-563972/<br></li>\n  </ul>\n<hr class=\"separator separator--dots\" />\n\n  <p>\n    The classic <code>TransportClient</code> is deprecated in Elasticsearch 7.0 and will be removed in version 8.0.\n  </p>",
            "image": "https://imteyazahmad.com/media/posts/3/ball-563972_1920-2.jpg",
            "author": {
                "name": "Imteyaz Ahmad"
            },
            "tags": [
                   "high level rest client",
                   "Java",
                   "Elasticsearch"
            ],
            "date_published": "2021-04-02T07:35:09-04:00",
            "date_modified": "2021-04-11T00:14:01-04:00"
        }
    ]
}
