Elasticsearch:如何在 Java 应用中创建 mappings 及进行批量写入

在我之前的文章 “Elasticsearch:使用最新的 Elasticsearch Java client 8.0 来创建索引并搜索”,我详细地描述了如何在 Java 客户端应用中创建一个索引并对它进行搜索。在那个例子里,我们并没有描述如何创建 mappings。最近,我看到有开发者在评论区里留言想知道如何创建 mappings 并使用 _bulk 来进行批量写入。今天的文章,我是继先前的文章 “Elasticsearch:使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群” 来进行的。在 Elastic Stack 8.x 平台,开始引入 HTTPS 的访问,所以前面的那篇文章是最好的开始。

我将使用 Elastic Stack 8.2 老进行展示。为了方便大家的学习,你可以在地址 GitHub - liu-xiao-guo/ElasticsearchJava-mapping-bulk8 下载下面所讲内容的源码。关于 Java client API 的查找,你可以参考链接 Overview (java-client 8.2.2 API) 

如何在 Java 应用中创建 mappings 及进行批量写入

如何在 Java 应用中创建 mappings 及进行批量写入_哔哩哔哩_bilibili

创建 mappings

其实在最新的 Java 客户端 API 中,它的使用非常像极了我们常见的在 console 中的命令。比如,我们可以使用如下的命令来创建一个索引:



1.  PUT test
2.  {
3.    "mappings": {
4.      "properties": {
5.        "id": {
6.          "type": "keyword"
7.        },
8.        "name": {
9.          "type": "text",
10.          "fields": {
11.            "keyword": {
12.              "type": "keyword",
13.              "ignore_above": 256
14.            }
15.          }
16.        },
17.        "price": {
18.          "type": "long"
19.        }
20.      }
21.    }
22.  }


复制代码

显然在上面,我们可以看见有一个叫做 mappings 的字段,当然它是操作与一个索引 test 上的。很自然的,在使用请求的时候,我们需要创建 mappings 这个定义。

首先,我们来把代码直接贴出来:

 1.          ElasticsearchIndicesClient indices = client.indices();

4.          // Firstly remove "products" if it exists
5.          try {
6.              DeleteIndexRequest delete_request = new DeleteIndexRequest.Builder()
7.                      .index("products")
8.                      .build();
9.              DeleteIndexResponse delete_response = indices.delete(delete_request);
10.              System.out.println(delete_response.acknowledged());

12.          } catch (Exception e) {
13.              // e.printStackTrace();
14.          }

16.          // Secondly remove "test" if it exists
17.          try {
18.              DeleteIndexRequest delete_request = new DeleteIndexRequest.Builder()
19.                      .index("test")
20.                      .build();
21.              DeleteIndexResponse delete_response = indices.delete(delete_request);
22.              System.out.println(delete_response.acknowledged());

24.          } catch (Exception e) {
25.              // e.printStackTrace();
26.          }
复制代码

在上面,它们相当于如下的指令:



1.  DELETE products
2.  DELETE test


复制代码

为了确保下面的命令成功,我们首先删除已经创建过的 products 及 test 索引,如果它们之前已经被创建过。这是一个很简单的操作,就是发送一个 DELETE 指令。

接下来,我们在一个文件中定义一个如下的 mappings:

mappings.json



1.  {
2.    "properties" : {
3.      "id" : {
4.        "type" : "keyword"
5.      },
6.      "name" : {
7.        "type" : "text",
8.        "fields" : {
9.          "keyword" : {
10.            "type" : "keyword",
11.            "ignore_above" : 256
12.          }
13.        }
14.      },
15.      "price" : {
16.        "type" : "long"
17.      }
18.    }
19.  }


复制代码

这是我们想要的一个 mapping。它定义了索引中想要的字段的类型。

我们接着使用如下的命令来创建一个叫做 test 的索引:

 1.         String mappingPath = System.getProperty("user.dir") + "/mappings.json";
2.          JsonpMapper mapper = client._transport().jsonpMapper();
3.          String mappings_str = new String(Files.readAllBytes(Paths.get(mappingPath)));
4.          System.out.println("mappings are: " +  mappings_str);
5.          JsonParser parser = mapper.jsonProvider()
6.                  .createParser(new StringReader( mappings_str ));

8.          client.indices()
9.                  .create(createIndexRequest -> createIndexRequest.index("test")
10.                          .mappings(TypeMapping._DESERIALIZER.deserialize(parser, mapper)));
复制代码

首先,我们读入 mappings.json 文件,并使用 client.indices 来创建 test 索引。显然和我们的 console 中的命令很相似。从一个叫做 test 的索引中创建一个 mappings。

当我们成功运行上面的命令后,我们可以在 Kibana 中进行查看:

GET test/_mapping
复制代码

它的响应为:



1.  {
2.    "test" : {
3.      "mappings" : {
4.        "properties" : {
5.          "id" : {
6.            "type" : "keyword"
7.          },
8.          "name" : {
9.            "type" : "text",
10.            "fields" : {
11.              "keyword" : {
12.                "type" : "keyword",
13.                "ignore_above" : 256
14.              }
15.            }
16.          },
17.          "price" : {
18.            "type" : "long"
19.          }
20.        }
21.      }
22.    }
23.  }


复制代码

接下来,我们使用另外一种方法来创建 mappings:

 1.          String mappings = "{\n" +
2.                  "  \"properties\" : {\n" +
3.                  "    \"id\" : {\n" +
4.                  "      \"type\" : \"keyword\" \n" +
5.                  "    },\n"+
6.                  "    \"name\" : {\n" +
7.                  "      \"type\" : \"text\",\n" +
8.                  "      \"fields\" : {\n" +
9.                  "        \"keyword\" : {\n" +
10.                  "          \"type\" : \"keyword\",\n" +
11.                  "          \"ignore_above\" : 256 \n" +
12.                  "        }\n" +
13.                  "      } \n" +
14.                  "    }, \n" +
15.                  "    \"price\" : { \n" +
16.                  "      \"type\" : \"long\" \n" +
17.                  "     } \n" +
18.                  "  }\n" +
19.                  "}\n";

21.          System.out.println( "mappings are: " + mappings );
22.          JsonpMapper mapper1 = client._transport().jsonpMapper();
23.          JsonParser parser1 = Json.createParser(new StringReader(mappings));
24.          CreateIndexRequest request_create =  new CreateIndexRequest.Builder()
25.                  .index("products")
26.                  .mappings(TypeMapping._DESERIALIZER.deserialize(parser1, mapper1))
27.                  .build();
28.          CreateIndexResponse response_create = indices.create(request_create);
29.          System.out.println(response_create.acknowledged());
复制代码

在上面,我使用了一个字符串 mappings 来定义索引 products 的 mappings。我们可以通过打印的方法来检查字符串的输出是否正确。我们必须确保这个字符串输出和我们在 console 里的一致性,否则会造成错误。接下来的代码和之前的一样。

当我们成功运行上面的代码后,我们可以在 Kibana 中进行查看:

GET products/_mapping
复制代码

它的响应是:



1.  {
2.    "products" : {
3.      "mappings" : {
4.        "properties" : {
5.          "id" : {
6.            "type" : "keyword"
7.          },
8.          "name" : {
9.            "type" : "text",
10.            "fields" : {
11.              "keyword" : {
12.                "type" : "keyword",
13.                "ignore_above" : 256
14.              }
15.            }
16.          },
17.          "price" : {
18.            "type" : "long"
19.          }
20.        }
21.      }
22.    }
23.  }


复制代码

显然它是按照我们的需求来创建的 mappings。

使用 _bulk 来进行批量写入

在我们写入的时候,_bulk 指令可以一次性大量写入我们的文档,从而提高效率。那么我们该如何在 Java 里进行实现呢?

 1.          Product prod1 = new Product("prod1", "washing machine", 42);
2.          Product prod2 = new Product("prod2", "TV", 42);

4.          List<Product> products = new ArrayList<Product>();
5.          products.add( prod1 );
6.          products.add( prod2 );

8.          BulkRequest.Builder br = new BulkRequest.Builder();
9.          for (Product product : products) {
10.              br.operations(op -> op
11.                      .index(idx -> idx
12.                              .index("products")
13.                              .id(product.getId())
14.                              .document(product)
15.                      )
16.              );
17.          }

19.          BulkResponse result = client.bulk(br.build());

21.          if (result.errors()) {
22.              System.out.println("Bulk had errors");
23.              for (BulkResponseItem item: result.items()) {
24.                  if (item.error() != null) {
25.                      System.out.println(item.error().reason());
26.                  }
27.              }
28.          }
复制代码

实际上它的操作也非常简单。如上面的代码所示,我们首先创建两个文档的列表,然后使用 BulkRequest 来创建请求。在请求中,我们使用了 index 的操作。上面的这个操作非常像如下的这个命令:



1.  POST _bulk
2.  { "index" : { "_index" : "produtcs", "_id" : "prod1" } }
3.  { "id" : "prod1", "name": "washing machine", "price": 42 }
4.  { "index" : { "_index" : "produtcs", "_id" : "prod2" } }
5.  { "id" : "prod2", "name": "TV", "price": 42 }


复制代码

运行上面的命令后,我们执行如下的命令来进行查看:

GET products/_search?filter_path=**.hits
复制代码

上面命令显示的结果为:



1.  {
2.    "hits" : {
3.      "hits" : [
4.        {
5.          "_index" : "products",
6.          "_id" : "prod1",
7.          "_score" : 1.0,
8.          "_source" : {
9.            "id" : "prod1",
10.            "name" : "washing machine",
11.            "price" : 42
12.          }
13.        },
14.        {
15.          "_index" : "products",
16.          "_id" : "prod2",
17.          "_score" : 1.0,
18.          "_source" : {
19.            "id" : "prod2",
20.            "name" : "TV",
21.            "price" : 42
22.          }
23.        }
24.      ]
25.    }
26.  }


复制代码

显然我们的写入是成功的,并且是一次请求,同时写入了两个文档。在实际的使用中,我们可以写入成百上千的文档。

好了,进行的文章就分享到这里。希望大家学到知识!

猜你喜欢

转载自juejin.im/post/7108538410989518855