怎么备份网站模板,网站建设公司特点,什么公司可以做网站等级保护,时尚网站模板代码本文是我们学院课程的一部分#xff0c;该课程的标题为Java开发人员的Elasticsearch教程 。 在本课程中#xff0c;我们提供了一系列教程#xff0c;以便您可以开发自己的基于Elasticsearch的应用程序。 我们涵盖了从安装和操作到Java API集成和报告的广泛主题。 通过我们简… 本文是我们学院课程的一部分该课程的标题为Java开发人员的Elasticsearch教程 。 在本课程中我们提供了一系列教程以便您可以开发自己的基于Elasticsearch的应用程序。 我们涵盖了从安装和操作到Java API集成和报告的广泛主题。 通过我们简单易懂的教程您将能够在最短的时间内启动并运行自己的项目。 在这里查看 1.简介 在本教程的上半部分我们仅通过命令行工具通过利用其大量RESTful API来掌握与Elasticsearch建立有意义的对话的技能。 这是非常少的知识但是当您开发Java / JVM应用程序时您将需要比命令行更好的选择。 幸运的是 Elasticsearch在这一领域提供了多种产品。 目录 1.简介 2.使用Java客户端API 3.使用Java Rest客户端 4.使用测试套件 5。结论 6.接下来 在本教程的这一部分中我们将学习如何通过本地Java API与Elasticsearch进行通信。 我们的方法是编写代码并在几个Java应用程序上工作使用Apache Maven进行构建管理使用出色的Spring Framework进行依赖关系接线和控制反转 并使用出色的JUnit / AssertJ作为测试支架。 2.使用Java客户端API 从早期版本开始 Elasticsearch随每个发行版一起分发专用的Java客户端API 也称为传输客户端。 它谈到了Elasticsearch本机传输协议因此施加了这样的约束客户端库的版本应至少与您使用的Elasticsearch发行版的主要版本匹配理想情况下客户端应具有完全相同的版本。 当我们使用Elasticsearch版本5.2.0 将相应的客户端版本依赖项添加到我们的pom.xml文件中是有意义的。 dependencygroupIdorg.elasticsearch.client/groupIdartifactIdtransport/artifactIdversion5.2.0/version
/dependency 由于我们选择了Spring Framework来驱动我们的应用程序因此实际上我们唯一需要的就是传输客户端配置。 Configuration
public class ElasticsearchClientConfiguration {Bean(destroyMethod close)TransportClient transportClient() throws UnknownHostException {return new PreBuiltTransportClient(Settings.builder()-.put(ClusterName.CLUSTER_NAME_SETTING.getKey(), es-catalog).build()).addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(localhost), 9300));}
} PreBuiltTransportClient遵循构建器模式 与我们很快将要看到的大多数类一样来构造TransportClient实例一旦存在我们就可以使用Spring Framework支持的注入技术来访问它 Autowired private TransportClient client; CLUSTER_NAME_SETTING值得我们注意它应该与我们要连接的Elasticsearch集群的名称完全匹配在本例中为es-catalog 。 太好了我们已经初始化了传输客户端那么该如何处理呢 本质上传输客户端公开了很多方法遵循流畅的界面样式以打开对Java代码中所有Elasticsearch API的访问。 要迈出第一步应该注意的是传输客户端在常规API和管理API之间有明确的分隔。 后者可以通过在传输客户端实例上调用admin()方法获得。 在翻开袖子弄脏手之前有必要提到 Elasticsearch Java API设计为完全异步的因此它们围绕两个关键抽象 ActionFuture?和ListenableActionFuture? 。 实际上 ActionFuture?只是一个普通的Java Future 其中添加了一些少数方法请继续关注。 另一方面 ListenableActionFuture?是更强大的抽象具有执行回调并将执行结果通知调用方的能力。 选择一种样式完全取决于您的应用程序需求因为这两种样式都有其优缺点。 事不宜迟让我们继续前进确保我们的Elasticsearch集群运行状况良好并已准备就绪。 final ClusterHealthResponse response client.admin().cluster().health(Requests.clusterHealthRequest().waitForGreenStatus().timeout(TimeValue.timeValueSeconds(5))).actionGet();assertThat(response.isTimedOut()).withFailMessage(The cluster is unhealthy: %s, response.getStatus()).isFalse(); 该示例非常简单明了。 我们要做的是向Elasticsearch集群查询其状态同时明确要求最多等待5 seconds以使状态变为green 如果不是这种情况。 在client.admin().cluster().health(...) client.admin().cluster().health(...)返回ActionFuture?所以我们必须调用actionGet方法之一来获取响应。 这是使用Elasticsearch Java API的另一种稍有不同的方式这次使用了prepareXxx方法家族。 final ClusterHealthResponse response client.admin().cluster().prepareHealth().setWaitForGreenStatus().setTimeout(TimeValue.timeValueSeconds(5)).execute().actionGet();assertThat(response.isTimedOut()).withFailMessage(The cluster is unhealthy: %s, response.getStatus()).isFalse(); 尽管这两个代码段均导致绝对相同的结果但后一个代码段是在链的末尾调用client.admin().cluster().prepareHealth().execute()方法该方法返回ListenableActionFuture? 。 在这个例子中它并没有太大的区别但是请牢记这一点因为我们将看到更多有趣的用例其中这样的细节实际上会改变游戏规则。 最后最后但并非最不重要的一点是任何API的异步特性并且Elasticsearch Java API也不例外假定对该操作的调用将花费一些时间并且调用者有责任决定如何处理该操作。 到目前为止我们仅在ActionFuture?实例上调用actionGet 它将有效地将异步执行转换为阻塞或ActionFuture? 同步调用。 此外我们没有在同意放弃之前等待执行完成的时间方面指定期望。 我们可以做得更好在本节的其余部分中我们将解决这两点。 一旦我们的Elasticsearch集群状态全部变为green 就该创建一些索引了就像我们在本教程的上一部分中所做的一样但是这次仅使用Java API。 创建catalog索引之前最好确保catalog索引尚不存在。 final IndicesExistsResponse response client.admin().indices().prepareExists(catalog).get(TimeValue.timeValueMillis(100));if (!response.isExists()) {...
} 请注意在上面的代码段中我们提供了完成操作的显式超时get(TimeValue.timeValueMillis(100)) 这实际上是execute().actionGet(TimeValue.timeValueMillis(100))的快捷方式。 对于catalog索引设置和映射类型我们将使用与本教程上半部分相同的JSON文件catalog-index.json 。 我们将遵循Apache Maven约定将其放置在src/test/resources文件夹中。 Value(classpath:catalog-index.json)
private Resource index; 幸运的是 Spring Framework大大简化了对类路径资源的注入因此我们在这里不需要做太多事情就可以访问catalog-index.json内容并将其直接提供给Elasticsearch Java API。 try (final ByteArrayOutputStream out new ByteArrayOutputStream()) {Streams.copy(index.getInputStream(), out);final CreateIndexResponse response client.admin().indices().prepareCreate(catalog).setSource(out.toByteArray()).setTimeout(TimeValue.timeValueSeconds(1)).get(TimeValue.timeValueSeconds(2));assertThat(response.isAcknowledged()).withFailMessage(The index creation has not been acknowledged).isTrue();
} 该代码块说明了利用setSource方法调用来处理Elasticsearch Java API的另一种方法。 简而言之我们只是以不透明的Blob或字符串的形式自己提供请求有效负载并将其按原样发送到Elasticsearch节点。 但是我们可以改用纯Java数据结构例如 final CreateIndexResponse response client.admin().indices().prepareCreate(catalog).setSettings(...).setMapping(books, ...).setMapping(authors, ...).setTimeout(TimeValue.timeValueSeconds(1)).get(TimeValue.timeValueSeconds(2)); 好的到此我们将结束传输客户端管理API并切换到文档和搜索API因为您通常会使用这些API。 我们记得 Elasticsearch说的是JSON因此我们必须以某种方式使用Java将书籍和作者转换为JSON表示形式。 实际上 Elasticsearch Java API通过支持对名为XContent的内容的通用抽象来提供XContent 例如 final XContentBuilder source JsonXContent.contentBuilder().startObject().field(title, Elasticsearch: The Definitive Guide. ...).startArray(categories).startObject().field(name, analytics).endObject().startObject().field(name, search).endObject().startObject().field(name, database store).endObject().endArray().field(publisher, OReilly).field(description, Whether you need full-text search or ...).field(published_date, new LocalDate(2015, 02, 07).toDate()).field(isbn, 978-1449358549).field(rating, 4).endObject(); 具有文档表示形式后我们可以将其发送给Elasticsearch进行索引。 为了兑现承诺这次我们希望采用真正的异步方式而不是等待响应而是以ActionListenerIndexResponse的形式提供通知回调。 client.prepareIndex(catalog, books).setId(978-1449358549).setContentType(XContentType.JSON).setSource(source).setOpType(OpType.INDEX).setRefreshPolicy(RefreshPolicy.WAIT_UNTIL).setTimeout(TimeValue.timeValueMillis(100)).execute(new ActionListener() {Overridepublic void onResponse(IndexResponse response) {LOG.info(The document has been indexed with the result: {}, response.getResult());}Overridepublic void onFailure(Exception ex) {LOG.error(The document has been not been indexed, ex);}}); 很好所以我们在books有了第一个文件 那authors呢 提醒一下这本书有多个作者因此是使用文档批量索引的绝佳时机。 final XContentBuilder clintonGormley JsonXContent.contentBuilder().startObject().field(first_name, Clinton).field(last_name, Gormley).endObject();final XContentBuilder zacharyTong JsonXContent.contentBuilder().startObject().field(first_name, Zachary).field(last_name, Tong).endObject(); XContent部分很清楚坦白地说您可能永远都不会使用这种选项而是希望对真实的类进行建模并使用一种出色的Java库来自动进行JSON转换。 但是以下片段非常有趣。 final BulkResponse response client.prepareBulk().add(Requests.indexRequest(catalog).type(authors).id(1).source(clintonGormley).parent(978-1449358549).opType(OpType.INDEX)).add(Requests.indexRequest(catalog).type(authors).id(2).source(zacharyTong).parent(978-1449358549).opType(OpType.INDEX)).setRefreshPolicy(RefreshPolicy.WAIT_UNTIL).setTimeout(TimeValue.timeValueMillis(500)).get(TimeValue.timeValueSeconds(1));assertThat(response.hasFailures()).withFailMessage(Bulk operation reported some failures: %s, response.buildFailureMessage()).isFalse(); 我们正在单批发送两个针对authors集合的索引请求。 您可能想知道这个parent(978-1449358549)含义要回答这个问题我们必须回想起 books和authors是使用父母/子女关系建模的。 因此在这种情况下 parent键是对books各个父文档的引用通过_id属性。 做得好所以我们知道如何使用索引以及如何使用Elasticsearch传输客户端Java API对文档建立索引。 现在是搜索时间 final SearchResponse response client.prepareSearch(catalog).setTypes(books).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(QueryBuilders.matchAllQuery()).setFrom(0).setSize(10).setTimeout(TimeValue.timeValueMillis(100)).get(TimeValue.timeValueMillis(200));assertThat(response.getHits().hits()).withFailMessage(Expecting at least one book to be returned).isNotEmpty(); 可以提出的最简单的搜索标准是匹配所有文档这就是我们在上面的摘录中所做的请注意我们明确将返回的结果数限制为10文档。 幸运的是 Elasticsearch Java API以QueryBuilders和QueryBuilder类的形式全面实现了Query DSL 因此编写和维护复杂的查询非常容易。 作为练习我们将构建与本教程的上一部分相同的复合查询 final QueryBuilder query QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(rating).gte(4)).must(QueryBuilders.nestedQuery(categories, QueryBuilders.matchQuery(categories.name, analytics),ScoreMode.Total)).must(QueryBuilders.hasChildQuery(authors, QueryBuilders.termQuery(last_name, Gormley),ScoreMode.Total)); 该代码看起来漂亮简洁易于阅读。 如果您热衷于使用Java编程语言的静态导入功能则查询看起来会更加紧凑。 final SearchResponse response client.prepareSearch(catalog).setTypes(books).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(query).setFrom(0).setSize(10).setFetchSource(new String[] { title, publisher }, /* includes */ new String[0] /* excludes */).setTimeout(TimeValue.timeValueMillis(100)).get(TimeValue.timeValueMillis(200));assertThat(response.getHits().hits()).withFailMessage(Expecting at least one book to be returned).extracting(sourceAsString, String.class).hasOnlyOneElementSatisfying(source - {assertThat(source).contains(Elasticsearch: The Definitive Guide.);}); 为了使两个版本的查询保持相同我们还通过setFetchSource方法提示搜索请求我们只对返回文档源的title和Publisher属性感兴趣。 好奇的读者可能想知道如何将聚合与搜索请求一起使用。 这是一个非常好的话题所以让我们先讨论一下。 与Query DSL一起 Elasticsearch Java API还提供了聚合DSL 围绕AggregationBuilders和AggregationBuilder类展开。 例如这就是我们可以通过publisher属性构建存储桶聚合的方法。 final AggregationBuilder aggregation AggregationBuilders.terms(publishers).field(publisher).size(10); 定义好聚合之后我们可以使用addAggregation方法调用将它们注入搜索请求中如下面的代码片段所示 final SearchResponse response client.prepareSearch(catalog).setTypes(books).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(QueryBuilders.matchAllQuery()).addAggregation(aggregation).setFrom(0).setSize(10).setTimeout(TimeValue.timeValueMillis(100)).get(TimeValue.timeValueMillis(200));final StringTerms publishers response.getAggregations().get(publishers);
assertThat(publishers.getBuckets()).extracting(keyAsString, String.class).contains(OReilly); 汇总的结果在响应中可用并且可以通过引用汇总名称例如本例中的publishers来检索。 但是要谨慎并谨慎使用正确的聚合类型以免以ClassCastException的形式出现意外。 因为已经定义了发布者聚合来将术语分组到存储桶中所以我们可以安全地将其从响应转换为StringTerms类实例。 3.使用Java Rest客户端 与使用Elasticsearch Java客户端API相关的缺点之一是要求与您正在运行的Elasticsearch版本独立版本或集群版本二进制兼容。 幸运的是自5.0.0分支的第一个版本发布以来 Elasticsearch在表上带来了另一个选择 Java REST client 。 它使用HTTP协议来倾诉Elasticsearch通过调用它的RESTful API端点是无视的版本Elasticsearch 从字面上看它是兼容所有Elasticsearch版本。 应当指出的是尽管Java REST客户端相当低级并且使用起来不像Java客户端API那样方便但实际上并非如此。 但是出于很多原因人们可能更喜欢使用Java REST客户端而不是Java客户端API与Elasticsearch进行通信因此值得进行自己的讨论。 首先让我们将相应的依赖项包含到我们的Apache Maven pom.xml文件中。 dependencygroupIdorg.elasticsearch.client/groupIdartifactIdrest/artifactIdversion5.2.0/version
/dependency 从配置的角度来看我们只需要通过调用RestClient.builder方法来构造RestClient的实例。 Configuration
public class ElasticsearchClientConfiguration {Bean(destroyMethod close)RestClient transportClient() {return RestClient.builder(new HttpHost(localhost, 9200)).setRequestConfigCallback(new RequestConfigCallback() {Overridepublic Builder customizeRequestConfig(Builder builder) {return builder.setConnectTimeout(1000).setSocketTimeout(5000);}}).build();}
} 我们在这里取得了一些进步但是请特别注意正确超时的配置因为Java REST客户端没有提供至少目前基于每个请求级别指定超时的方法。 这样我们可以使用Spring Framework为我们提供的相同接线技术在任何地方注入RestClient实例 Autowired private RestClient client; 为了公平地比较Java客户端API和Java REST客户端 我们将剖析上一部分中看到的几个示例并通过检查Elasticsearch集群运行状况来确定阶段。 Test
public void esClusterIsHealthy() throws Exception {final Response response client.performRequest(HttpGet.METHOD_NAME, _cluster/health, emptyMap());final Object json defaultConfiguration().jsonProvider().parse(EntityUtils.toString(response.getEntity()));assertThat(json, hasJsonPath($.status, equalTo(green)));
} 确实差异是显而易见的。 您可能会猜到 Java REST客户端实际上是更通用知名和受人尊敬的Apache Http Client库的一个瘦包装。 响应以字符串或字节数组的形式返回调用者有责任将其转换为JSON并提取必要的数据。 为了在测试断言中处理该问题我们已经启用了出色的JsonPath库但是您可以在这里自由选择。 一组performRequest方法是使用Java REST客户端 API进行同步或阻止通信的典型方法。 另外还有一类performRequestAsync方法应该在完全异步的流中使用。 在下一个示例中我们将使用其中之一来将文档编books 。 用Java语言表示类似于JSON的结构的最简单方法是使用普通的旧MapString, Object如下面的代码片段所示。 final MapString, Object source new LinkedHashMap();
source.put(title, Elasticsearch: The Definitive Guide. ...);
source.put(categories, new Map[] {singletonMap(name, analytics),singletonMap(name, search),singletonMap(name, database store)}
);
source.put(publisher, OReilly);
source.put(description, Whether you need full-text search or ...);
source.put(published_date, 2015-02-07);
source.put(isbn, 978-1449358549);
source.put(rating, 4); 现在我们需要将此Java结构转换为有效的JSON字符串。 这样做有很多方法但是我们将利用json-smart库因为它已经可以作为JsonPath库的传递依赖项使用 。 final HttpEntity payload new NStringEntity(JSONObject.toJSONString(source), ContentType.APPLICATION_JSON); 准备好有效负载后没有什么可以阻止我们调用Elasticsearch的 Indexing API将一本书添加到books集合中。 client.performRequestAsync(HttpPut.METHOD_NAME, catalog/books/978-1449358549,emptyMap(),payload,new ResponseListener() {Overridepublic void onSuccess(Response response) {LOG.info(The document has been indexed successfully);}Overridepublic void onFailure(Exception ex) {LOG.error(The document has been not been indexed, ex);}}); 这次我们决定不等待响应而是提供一个回调 ResponseListener实例以保持流真正异步。 最后最好了解执行或多或少切合实际的搜索请求并解析结果所需的内容。 如您所料 Java REST客户端不提供围绕Query DSL的任何流畅的API因此我们不得不再回退一次MapString, Object以便构建搜索条件。 final MapString, Object authors new LinkedHashMap();
authors.put(type, authors);
authors.put(query, singletonMap(term,singletonMap(last_name, Gormley))
);final MapString, Object categories new LinkedHashMap();
categories.put(path, categories);
categories.put(query,singletonMap(match, singletonMap(categories.name, search))
);final MapString, Object query new LinkedHashMap();
query.put(size, 10);
query.put(_source, new String[] { title, publisher });
query.put(query, singletonMap(bool,singletonMap(must, new Map[] {singletonMap(range,singletonMap(rating, singletonMap(gte, 4))),singletonMap(has_child, authors),singletonMap(nested, categories)}))
); 公开解决问题需要付出的代价是编写许多繁琐且容易出错的代码。 在这方面 Java客户端API的一致性和简洁性确实产生了巨大的差异。 您可能会争辩说实际上可能有人依赖更简单更安全的技术例如数据传输对象 值对象 或者甚至具有带有占位符的JSON搜索查询模板但重点是Java REST客户端在此提供了一些帮助。时刻。 final HttpEntity payload new NStringEntity(JSONObject.toJSONString(query), ContentType.APPLICATION_JSON);final Response response client.performRequest(HttpPost.METHOD_NAME, catalog/books/_search, emptyMap(), payload);final Object json defaultConfiguration().jsonProvider().parse(EntityUtils.toString(response.getEntity()));assertThat(json, hasJsonPath($.hits.hits[0]._source.title, containsString(Elasticsearch: The Definitive Guide.))); 在此处添加的内容不多只需查阅格式的Search API文档然后从响应中提取您感兴趣的详细信息就像我们通过声明_source的title property所做的那样。 到此我们结束了关于Java REST client的讨论。 坦率地说与选择Java生态系统所具有的通用HTTP客户端之一相比使用它是否有任何好处还不清楚。 确实这确实是一个令人担忧的问题但是请记住 Java REST客户端是Elasticsearch系列的新成员希望我们很快就会看到很多激动人心的功能。 4.使用测试套件 随着我们的应用程序变得越来越复杂和分散正确的测试变得前所未有的重要。 多年来 Elasticsearch提供了卓越的测试工具 以简化严重依赖其搜索和分析功能的应用程序的测试。 更具体地说您的项目中可能需要两种测试 单元测试 那些正在独立测试单个单元例如fe类的测试通常不需要具有正在运行的Elasticsearch节点或集群。 这些测试由ESTestCase和ESTokenStreamTestCase支持。 集成测试 这些测试正在测试完整的流程通常需要至少一个运行的Elasticsearch节点或集群以强调更实际的场景。 这些测试由ESIntegTestCase ESSingleNodeTestCase和ESBackCompatTestCase 。 让我们再翻一次袖子学习如何使用Elasticsearch提供的测试支架来开发我们自己的测试套件。 我们将从声明依赖关系开始仍然使用Apache Maven 。 dependencygroupIdorg.apache.lucene/groupIdartifactIdlucene-test-framework/artifactIdversion6.4.0/versionscopetest/scope
/dependencydependencygroupIdorg.elasticsearch.test/groupIdartifactIdframework/artifactIdversion5.2.0/versionscopetest/scope
/dependency 尽管这不是绝对必要的但我们还将显式依赖项添加到JUnit 将其版本提高到4.12 。 dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scopeexclusionsexclusiongroupIdorg.hamcrest/groupIdartifactIdhamcrest-core/artifactId/exclusion/exclusions
/dependency 我们在这里需要提请注意 Elasticsearch测试框架对依赖项异常敏感确保您的应用程序不会陷入每个Java开发人员都熟知的jar hell的问题 。 Elasticsearch测试框架所做的一项预检查是确保classpath中没有重复的类。 通常您可能会在此过程中使用其他出色的测试库但如果您的Elasticsearch测试用例突然开始无法通过初始化阶段则很可能是由于检测到jar地狱问题因此必须进行一些排除。 还有一件事很可能您需要在测试运行期间通过将tests.security.manager属性设置为false来关闭安全管理器。 可以通过将-Dtests.security.managerfalse参数直接传递给JVM或使用Apache Maven插件配置来完成。 plugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-surefire-plugin/artifactIdversion2.19.1/versionconfigurationargLine-Dtests.security.managerfalse/argLine/configuration
/plugin 太棒了所有前提条件都得到了解释我们都准备开始开发第一个测试用例。 适用于Elasticsearch的上下文中的单元测试对于测试您自己的分析器 令牌生成 器 令牌过滤器和字符过滤器非常有用。 在这方面我们没有做太多事情但是集成测试是一个截然不同的故事。 让我们看看如何启动具有3节点的Elasticsearch集群。 ClusterScope(numDataNodes 3)
public class ElasticsearchClusterTest extends ESIntegTestCase {
} ……从字面上看就是这样。 当然尽管群集已启动但它没有索引或未预先配置的内容。 让我们添加一些测试背景以使用相同的catalog-index.json文件创建catalog索引及其映射类型。 Before
public void setUpCatalog() throws IOException {try (final ByteArrayOutputStream out new ByteArrayOutputStream()) {Streams.copy(getClass().getResourceAsStream(/catalog-index.json), out);final CreateIndexResponse response admin().indices().prepareCreate(catalog).setSource(out.toByteArray()).get();assertAcked(response);ensureGreen(catalog);}
} 如果您已经识别出此代码那是因为我们使用的是之前了解的相同传输客户端 如果您需要Java REST客户端实例 Elasticsearch测试脚手架会在client()或admin()方法之后为您提供该功能并与getRestClient()一起提供。 每次测试运行后清理集群都是一件好事幸运的是我们可以使用cluster()方法来访问几个非常有用的操作例如 After
public void tearDownCatalog() throws IOException, InterruptedException {cluster().wipeIndices(catalog);
} 总体而言 Elasticsearch测试工具的目标是两个目标简化最常见的任务我们已经看到了client() admin() cluster()实际运行以及轻松进行验证声明或期望例如 ensureGreen(...) assertAcked(...) 。 官方文档有专门的部分介绍了辅助方法和断言因此请看一看。 首先空索引中应该没有文档因此我们的第一个测试用例将明确声明这一事实。 Test
public void testEmptyCatalogHasNoBooks() {final SearchResponse response client().prepareSearch(catalog).setTypes(books).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(QueryBuilders.matchAllQuery()).setFetchSource(false).get();assertNoSearchHits(response);
} 一个简单但是创建真实文档呢 Elasticsearch测试框架具有多种有用的方法可以为大多数类型生成随机值。 我们可以利用它来创建一本书将其添加到图书catalog索引中并对其发出查询。 Test
public void testInsertAndSearchForBook() throws IOException {final XContentBuilder source JsonXContent.contentBuilder().startObject().field(title, randomAsciiOfLength(100)).startArray(categories).startObject().field(name, analytics).endObject().startObject().field(name, search).endObject().startObject().field(name, database store).endObject().endArray().field(publisher, randomAsciiOfLength(20)).field(description, randomAsciiOfLength(200)).field(published_date, new LocalDate(2015, 02, 07).toDate()).field(isbn, 978-1449358549).field(rating, randomInt(5)).endObject();index(catalog, books, 978-1449358549, source);refresh(catalog);final QueryBuilder query QueryBuilders.nestedQuery(categories, QueryBuilders.matchQuery(categories.name, analytics),ScoreMode.Total);final SearchResponse response client().prepareSearch(catalog).setTypes(books).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(query).setFetchSource(false).get();assertSearchHits(response, 978-1449358549);
} 如您所见除了categories之外大多数书籍属性都是随机生成的因此我们可以通过它们可靠地进行搜索。 Elasticsearch测试支持提供了许多有趣的机会不仅可以测试成功的结果而且可以模拟现实的集群行为和错误的条件这里的internalCluster()提供的辅助方法非常有用。 对于像Elasticsearch这样的复杂分布式系统此类测试的价值是无价的因此请利用可用的选项来确保部署到生产中的代码健壮并能够应对故障。 举个简单的例子我们可以在运行搜索请求时关闭随机数据节点并断言它们仍在处理中。 Test
public void testClusterNodeIsDown() throws IOException {internalCluster().stopRandomDataNode();final SearchResponse response client().prepareSearch(catalog).setTypes(books).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(QueryBuilders.matchAllQuery()).setFetchSource(false).get();assertNoSearchHits(response);
} 我们只是简单介绍了Elasticsearch测试工具的功能。 希望您在组织中实践测试驱动的开发并且我们所研究的示例可以很好地为您提供起点。 5。结论 在本教程的这一部分中我们学习了Elasticsearch开箱即用提供的两种Java客户端API Transport客户端和REST客户端 。 您可能会发现很难选择要使用哪种Java客户端API但是总的来说它高度依赖于应用程序。 在大多数情况下 传输客户端是最佳选择但是如果您的项目仅使用几个Elasticsearch API或功能的非常有限的子集则REST客户端可能是一个更好的选择。 另外我们不要忘记Java REST客户端是相当新的并且肯定会在将来的版本中进行改进因此请密切注意它。 当我们剖析传输客户端时 已经指出了它的完全异步性质。 尽管这绝对是一件好事但我们已经看到它基于回调更确切地说是侦听器这可能会Swift导致称为回调hell的问题。 强烈建议尽早解决此问题幸运的是有很多库和可用的替代品例如RxJava 2和Project Reactor Java 9也在赶上。 最后但并非最不重要的一点是我们浏览了Elasticsearch的 测试工具 并有机会认识到它为Java / JVM开发人员提供的巨大帮助。 6.接下来 在接下来的部分 即教程的最后一部分 我们将讨论围绕Elasticsearch的出色项目的生态系统。 希望您再一次对Elasticsearch的功能感到惊讶为您打开它的适用性的新视野。 所有项目的完整源代码都可以下载 elasticsearch-client-rest elasticsearch-testing elasticsearch-client-java 翻译自: https://www.javacodegeeks.com/2017/03/elasticsearch-java-developers-elasticsearch-java.html