MyBlog


ES总结六:java API

<p>[TOC]</p> <h1>简介</h1> <p>我们在前面提到过Elasticsearch底层依赖于Lucene库,而Lucene库完全是Java编写的,RESTflilAPI发送的请求最后都是通过Java执行的。就可行性来讲,JavaAPI比RESTfiilAPI功能更强大。不论是文档的CRUD查询、批量操作、统计操作,还是获取集群信息、索引和集群管理,java都可以做到。</p> <h1>maven依赖</h1> <pre><code class="language-java">&lt;dependency&gt; &lt;groupId&gt;org.elasticsearch.client&lt;/groupId&gt; &lt;artifactId&gt;transport&lt;/artifactId&gt; &lt;version&gt;{version}&lt;/version&gt; &lt;/dependency&gt;</code></pre> <h1>连接到集群</h1> <p>Elasticsearch的Javaclient对象可以执行多种操作:</p> <ul> <li>在现有的群集上执行标准的indexgetdelete和search操作。</li> <li>在运行的群集上执行管理任务。</li> </ul> <p>获得一个Elasticsear chclient对象非常简单,最常用的方式是创建一个可以连接到Elasticsearch集群的传输机对象TransportClient。 需要注意的是,client对象一定要和集群中的节点具有相同的版本,如果客户端和服务器版本不一致,就会导致有些功能无法使用,最理想的情况是客户端和服务器版本保持一致。</p> <h2>传输机连接</h2> <p>使用TransportClient创建的client对象可以通过传输模块远程与Elasticsearch集群建立连接。<strong>这种方式只会连接到集群而不会加入集群</strong>,client对象知道一个或多个传输地址,通过轮询调度的方式和服务器交互</p> <pre><code class="language-java">TransportClient client = new PreBuiltTransportClient(Settings.EMPTY) .addTransportAddress(newInetSocketTransportAddress (InetAcidress.getByName("hostl"),9300)) .addTransportAddress(newInetSocketTransportAddress (InetAddress.getByName("host2"),9300));</code></pre> <p>Settings对象中可以添加配置信息。如果在配置文件中设置的Elasticsearch集群名称不是默认的elasticsearch,就需要在Settings对象中指定集群名称:</p> <pre><code class="language-java">Settings settings=Settings.builder().put("cluster.name","myClusterName") .build(); TransportClient client = new PreBuiltTransportClient(settings);</code></pre> <p>TransportClient对象自带集群探测功能,可以自动添加新的主机、自动移除旧的主机。如果想要打开集群探测功能,就需要设置client.transport.sniff的属性为true:</p> <pre><code class="language-java">Settings settings=Settings.builder().put("client.transport.sniff",true) .build(); TransportClient client = new PreBuiltTransportClient(settings);</code></pre> <p>更多TransportClient的配置如下。 •client.transport.ignoreclustername 设为true会忽略节点的集群名称验证。•client.transport.pingtimeout 设置ping命令的响应时间,默认5秒。•client.transport.nodessamplerinterval 设置检查节点可用性的频率,默认值是5秒。</p> <h2>节点连接</h2> <p>节点连接的思路是把应用程序作为Elasticsearch的一个节点,我们的应用程序作为Elasticsearch集群的一部分,客户端作为一个新的节点和集群中的其他节点建立连接。这样可以减少客户端和服务器之间的交互次数,但是这种方法并不总是可行,比如集群不在同一个局域网中。推荐使用传输机方式创建client对象。</p> <h2>索引管理</h2> <p>这一小节介绍如何通过ElasticsearchJavaAPI进行索引的创建、删除、刷新、设置别名、设置mapping等索引管理操作。索引管理是通过一个IndicesAdminClient对象发送各种操作请求,获取IndicesAdminClient对象的方式如下:</p> <pre><code class="language-java">IndicesAdminClient indicesAdminClient=client.admin().indices();</code></pre> <p>判断索引是否存在:</p> <pre><code class="language-java">IndicesExistsResponse exResponse =indicesAdminClient .prepareExists("indexName").get();</code></pre> <p>判 断type是 否 存 在:</p> <pre><code class="language-java">TypesExistsResponse existsResponse=indicesAdminClient .prepareTypesExists("indexName") .setTypes("typel","type2") .get();</code></pre> <p>创建一个索引,索引名必须小写</p> <pre><code class="language-java">CreateIndexResponse cResponse=indicesAdminClient .prepareCreate("indexName").get();</code></pre> <p>创 建 索 引 并 设 置Settings</p> <pre><code class="language-java">CreateIndexResponse cResponse=indicesAdminClient.prepareCreate("twitter") .setSettings(Settings.builder() .put("index.number_of_shards",3) .put("index.number_of_replicas",2)) .get()</code></pre> <p>更新副本</p> <pre><code class="language-java">UpdateSettingsResponse upResponse=indicesAdminClient .prepareUpdateSettings("twitter") .setSettings(Settings.builder() .put("index.number_of_replicas",0)) .get();</code></pre> <p>设置mapping</p> <pre><code class="language-java">CreatelndexResponse cResponse=indicesAdminClient .prepareCreate("twitter") .addMapping("tweet",XContentFactory.jsonBuilder() .startObject().startObject("properties") .startObject("name") .field("type","keyword") .endObject().endObject().endObject()) .get();</code></pre> <p>获取mapping</p> <pre><code class="language-java">GetMappingsResponse mResponse=indicesAdminClient .prepareGetMappings("indexname").get(); ImmutableOpenMap&lt;String/MappingMetaData&gt;mapings=mResponse.getMappings() .get("indexname"); MappingMetaDatametatda=mapings.get("typename");</code></pre> <p>删 除 索 引</p> <pre><code class="language-java">DeleteIndexResponse dResponse=indicesAdminClient.prepareDelete("indexname") .get();</code></pre> <p>刷 新</p> <pre><code class="language-java">indicesAdminClient.prepareRefresh().get(); indicesAdminClient.prepareRefresh("indexname").get(); indicesAdminClient.prepareRefresh("indexname","typename").get();</code></pre> <p>关 闭 索 引</p> <pre><code class="language-java">CloselndexResponse clResponse=indicesAdminClient.prepareClose("indexname").get();</code></pre> <p>打 开 索 引</p> <pre><code class="language-java">OpenlndexResponseopResponse.prepareOpen("indexname").get();indicesAdminClient</code></pre> <p>设 置 别 名</p> <pre><code class="language-java">IndicesAliasesResponse aResponse=indicesAdminClient.prepareAliases().addAlias("indexName","aliasesName").get();</code></pre> <p>获 取 别 名</p> <pre><code class="language-java">GetAliasesResponse gResponse=indicesAdminClient.prepareGetAliases("aliasesname").get();</code></pre> <h2>文档管理</h2> <p>新建文档 索引文档API可以把一个JSON格式的文档索引到特定的索引中,并使该文档是可搜索的</p> <pre><code class="language-java">IndexResponse //doc1是json化的文档 response=client.preparelndex("twitter","tweet","3").setSource(doc1)</code></pre> <p>获取文档 GetAPI可以实现通过文档id读取一个JSON格式的文档。下面的例子是读取索引名为twitter类型名为tweetid为1的文档:</p> <pre><code class="language-java">GetResponse response=client.prepareGet("twitter","tweet","1").get();</code></pre> <p>GetResponse对象提供的常用方法如下:</p> <ul> <li>isExists()如果要读取的文档存在,就返回true,否则返回false</li> <li>getlndex()返回请求文档的索引名。</li> <li>getType()返回请求文档的类型名。</li> <li>getld()返回请求文档的ID</li> <li>getVersion()返回文档版本信息。</li> <li>getSourceAsBytes():以二进制数组方式读取文档内容。</li> <li>getSourceAsMap():以map形式读取文档内容。</li> <li>getSourceAsString():以文本方式读取文档内容。</li> <li>isSourceEmpty()判断文档内容是否为空</li> </ul> <p>删除文档 和读取文档的API类似,DeleteAPI可以实现通过文档id删除Elasticsearch中的文档,以删除索引名为twitter类型名为tweetid为1的文档为例,代码如下:</p> <pre><code class="language-java">DeleteResponse response=client.prepareDelete("twitter","tweet","1").get();</code></pre> <p>DeleteResponse对象提供的常用方法如下。</p> <ul> <li>status()删除成功,返回OK;删除失败,返回NOT_FOUND</li> <li>getType()返回删除请求文档的类型。</li> <li>getld()返回删除请求文档的ID</li> <li>getVersion()返回删除请求文档的版本信息</li> </ul> <p>更新文档 Elasticsearch提供了多种更新文档的API,主要有使用UpdateRequest对象、使用内嵌脚本、使用prepareUpdate()方法这3种。</p> <pre><code class="language-java">UpdateRequestUpdateRequest=newUpdateRequest(); UpdateRequest.index("twitter"); UpdateRequest.type("tweet"); UpdateRequest.id(’’1"); UpdateRequest.doc(jsonBuilder().startObject().field("gender","male").endObject()); client.update(UpdateRequest).get();</code></pre> <p>或者</p> <pre><code class="language-java">client.prepareUpdate("ttl","doc","1").setScript(newScript("ctx•一source.gender=\"male\"",ScriptService.ScriptType.INLINE,null,null))•get(); client.prepareUpdate("ttl","doc","1").setDoc(jsonBuilder().startObject().field("gender","male").endObject()).get();</code></pre> <p>Elasticsearch还支持upsert操作,如果文档存在,就执行修改操作;如果文档不存在,就再创建一个新的文档.。</p> <h2>搜索详解</h2> <p>和REST接口的查询DSL一样,Elasticsearch也提供了Java接口的查询DSL构造查询对象的工厂类是QueryBuilders,只要查询语句准备好了就可以使用搜索相关的API。 首先创建一个matchquery的对象:</p> <pre><code class="language-java">QueryBuilder matchQuery=QueryBuilders.matchQuery("title","Java编程").operator(Operator.AND);</code></pre> <p>查询</p> <pre><code class="language-java">SearchResponse response=EsUtils.getSingleTransportClient().prepareSearch("books") .setQuery(matchQuery).highlighter(highlighter).setSize(100).get();</code></pre> <p>全文查询 使用ElasticsearchJavaAPI构造各种全文级别查询的例子如下。 •MatchAll</p> <pre><code class="language-java">QueryBuildermatchAUQuery=QueryBuilders.matchAllQuery();</code></pre> <p>•match_phrase</p> <pre><code class="language-java">QueryBuildermatchPhraseQuery=QueryBuilders.matchPhraseQuery("foo","helloworld");</code></pre> <p>•match_phrase_prefix</p> <pre><code class="language-java">QueryBuildermatchPhrasePrefixQuery=QueryBuilders.matchPhrasePrefixQuery("foo","hellow");</code></pre> <p>•multimatch</p> <pre><code class="language-java">QueryBuildermultiMatchQuery=QueryBuilders.multiMatchQuery("kimchy","user","message");</code></pre> <p>•common</p> <pre><code class="language-java">QueryBuildercommonTermsQuery=QueryBuilders.commonTermsQuery("name","kimchy");</code></pre> <p>•querystring</p> <pre><code class="language-java">QueryBuilderqueryStringQuery=QueryBuilders.queryStringQuery(n+kimchy-elasticsearch");</code></pre> <p>•simplequerystring</p> <pre><code class="language-java">QueryBuilderqb=QueryBuilders.simpleQueryStringQuery("+kimchy-elasticsearch");</code></pre> <p>词项查询</p> <p>term</p> <pre><code class="language-java">QueryBuildertermQuery=QueryBuilders.termQuery("title","java");</code></pre> <p>terms</p> <pre><code class="language-java">QueryBuildertermsQuery=QueryBuilders.termsQuery("title","java","python");</code></pre> <p>range</p> <pre><code class="language-java">QueryBuilderrangeQuery=QueryBuilders.rangeQuery("price").from(50)</code></pre> <p>exist</p> <pre><code class="language-java">QueryBuilderexistsQuery=QueryBuilders.existsQuery("language");</code></pre> <p>prefix</p> <pre><code class="language-java">QueryBuilderprefixQuery=QueryBuilders•prefixQuery("description","win");</code></pre> <p>wildcard</p> <pre><code class="language-java">QueryBuilderwildcardQuery=QueryBuilders•wildcardQuery("author","张若")</code></pre> <p>regexp</p> <pre><code class="language-java">QueryBuilderregexpQuery=QueryBuilders.regexpQuery("author","Br.*")</code></pre> <p>fuzzy</p> <pre><code class="language-java">QueryBuilderfuzzyQuery=QueryBuilders.fuzzyQuery("title","javascritp")</code></pre> <p>type</p> <pre><code class="language-java">QueryBuildertypeQuery=QueryBuilders•typeQuery("IT");</code></pre> <p>ids</p> <pre><code class="language-java">QueryBuilderidsQuery=QueryBuilders.idsQuery().ids("3","5");</code></pre> <p>复合查询 bool 使用bool查询查找title字段中包含关键词java,并且价格不高于70,description字段可以包含也可以不包含虚拟机的书籍,构造boolQuery的代码如下:</p> <pre><code class="language-java">QueryBuildermatchQueryl=QueryBuilders.matchQuery("title","Java"); QueryBuildermatchQuery2=QueryBuilders.matchQuery("description","虚拟机"); QueryBuilderrangeQuery=QueryBuilders.rangeQuery("price").gte(70); QueryBuilderboolQuery=QueryBuilders .boolQuery() .must(matchQueryl) .should(matchQuery2) .mustNot(rangeQuery);</code></pre> <h2>聚合查询</h2> <p>指标聚合,求最小值、求和、求平均值、基本统计、高级统计、基数统计、百分位统计的核心代码如下。</p> <pre><code class="language-java">MinAggregationBuilderminAgg=AggregationBuilders.min("agg").field("price"); SearchResponseresponse=client.prepareSearch("books").addAggregation(minAgg).execute().actionGet(); Minmin=response.getAggregations().get("agg"); double minValue=min.getValue();</code></pre> <p>最大值</p> <pre><code class="language-java">SumAggregationBuilder sumAgg=AggregationBuilders.sum("agg").field("price");</code></pre> <p>平均</p> <pre><code class="language-java">AvgAggregationBuilder avgAgg = AggregationBuilders.avg("agg").field("price");</code></pre> <p>stats</p> <pre><code class="language-java">StatsAggregationBuilder statsAgg=AggregationBuilders.stats("agg").field("price");</code></pre> <p>Extended Stats</p> <pre><code class="language-java">ExtendedStatsAggregationBuilder extendedStatsAgg=AggregationBuilders.extendedStats("agg").field("price");</code></pre> <p>桶聚合 terms</p> <pre><code class="language-java">TermsAggregationBuildertermAgg=AggregationBuilders.terms("per_count”.field("language"); SearchResponseresponse=EsUtils.getSingleTransportClient()•prepareSearch("books").addAggregation(termAgg).execute().actionGet(); Termsgenders=response.getAggregations().get("per_countn);</code></pre> <p>filter</p> <pre><code class="language-java">FilterAggregationBuilderfilterAgg=AggregationBuilders•filter(agg",QueryBuilders.termQuery("title","java"));SearchResponseresponse=client().prepareSearch("books").addAggregation(filterAgg).execute().actionGet(); Filteragg=response.getAggregations().get("agg");</code></pre> <h1>集群管理</h1> <p>和索引管理类似,集群管理通过创建ClusterAdminClient对象可以获取集群和索引的健康状态、集群状态。</p> <pre><code class="language-java">ClusterHealthResponsehealths=client().admin()•cluster().prepareHealth().get(); StringclusterName=intnumberOfDataNodeshealths.getClusterName(); healths.getNumberOfDataNodes(); intnumberOfNodes=healths.getNumberOfNodes();</code></pre>

页面列表

ITEM_HTML