`
weitao1026
  • 浏览: 1061709 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

实时搜索引擎Elasticsearch(5)——Java API的使用

 
阅读更多

介绍了使用Rest方式调用ES的聚合API。Rest API使用了HTTP协议,按理来说,可以直接使用类似HttpClient的工具直接调用Rest API。虽然笔者并没有尝试过,但稍微想想一下就知道这种方法是可行的。这种方法主要有下面几个弊端:

  1. 需要开启ES的Http服务和端口。ES提供的Http服务功能非常全面,没有提供权限控制,防护也比较脆弱。一旦遭到破解,则数据面临极大的风险。所以,建议在生产中关闭Http服务,或者自己增加一层代理来实现权限控制。
  2. 调用比较困难。Rest API的核心是url和post数据,url直接需传入字符串,这样就不能使用IDE的查错功能。需要记忆的东西太多,不确定时就要去查API,影响开发效率。
  3. Http协议的一大特点是无连接性。也就是每一次请求都需要建立新的连接,我们知道tcp连接是比较耗时的过程。从性能的角度来说,直接使用Rest API也是不合适的。

ES所提供的Http服务适合用作集群状态和数据的监控,而不适合直接用于数据操作。ES提供了多种语言(包括JavaPythonPHP、Ruby等)版本的Client API,可以使用这些Client API编程实现数据操作功能。作为一个Java语言编程者,本文主要介绍使用Java版本的Client来操作数据。使用Java API需要依赖ES所提供的jar包,我们使用maven来下载所需的依赖包,maven依赖定义如下:

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>1.5.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

version表示依赖包的版本,可以输入任意存在的版本,本文的示例中使用1.5.0版的API。注意,建议API的版本与ES集群所使用的版本保持一致,以免出现因版本不一致而导致的冲突。

本文的主要内容包括:

  1. 介绍两类Client,解释它们的之间的差异;
  2. 使用Client进行index、document和聚合相关的操作。

1. Client

ES中所有的Java API调用都要使用Client对象,ES为API调用者提供了两类Client对象:NodeClient和TransportClient。下面来讲讲这两类Client的差异和使用场景。

1.1 NodeClient

NodeClient是一种嵌入式节点客户端。它首先在客户端启动一个节点(Node),并加入同名集群内。这个节点可以保存数据,并且数据能够被索引。然后从这个节点中获取Client,这类Client就是NodeClient。NodeClient无需指明ES服务端的地址,操作的数据位于启动的节点所在的集群中。下面是获得NodeClient的代码:

import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.node.Node;
import static org.elasticsearch.node.NodeBuilder.nodeBuilder;

public class MyNodeClient {

    public static void main(String[] args) {
        // 启动一个本地节点,并加入子网内的ES集群
        Node node = nodeBuilder()
                    .clusterName("elasticsearch") // 要加入的集群名为elasticsearch
                    // .client(true) //如果设置为true,则该节点不会保存数据
                    .data(true) // 本嵌入式节点可以保存数据
                    .node(); // 构建并启动本节点

        // 获得一个Client对象,该对象可以对子网内的“elasticsearch”集群进行相关操作。
        Client nodeClient = node.client();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

运行这段代码之后,可以看到工程中新增了一个data文件夹,这是因为data(true)将Node设置为可以存放数据的节点,数据正是放在了data文件夹下。

新增加的data文件夹

NodeClient适合用作单元或集成测试,而不适合用于生产环境。

1.2 TransportClient

TransportClient连接远端的ES集群,其本身并不会加入集群。创建TransportClient的代码如下:

import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;

import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;

public class MyTransportClient {

    public static void main(String[] args) {
        // 配置信息
        Settings esSetting = settingsBuilder()
                                .put("cluster.name", "elasticsearch")
                                .build();
        TransportClient transportClient = new TransportClient(esSetting);

        // 添加连接地址
        TransportAddress address = new InetSocketTransportAddress("192.168.1.110", 9300);
        TransportAddress address2 = new InetSocketTransportAddress("192.168.1.111", 9300);
        transportClient.addTransportAddress(address);
        transportClient.addTransportAddress(address2);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

TransportClient适合用于生产环境中。

2. Index操作

本小节介绍如果使用Java API创建和删除索引。

2.1 创建索引

废话先不说,上代码先。下面的方法创建一个索引,并同时创建一个mapping。mapping可以传入符合格式要求的json字符串。一般情况下,我们可以使用下面的方式来生成所需的json字符串。

  1. 手动拼接json字符串
  2. 使用类似jackson的工具将对象转换为相应的json字符串
  3. 使用ES内置的XContentFactory.jsonBuilder()来创建json字符串。

本文的示例中均使用ES自带的XContentFactory.jsonBuilder()来构建json字符串。

/**
 * 创建一个索引
 * @param indexName 索引名
 */
public void createIndex(String indexName) {
    try {
        CreateIndexResponse indexResponse = this.client
                                .admin()
                                .indices()
                                .prepareCreate(indexName)
                                .get();

        System.out.println(indexResponse.isAcknowledged()); // true表示创建成功
    } catch (ElasticsearchException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如果需要再索引上新建mapping,可通过下面的代码来实现。

/**
 * 给索引增加mapping。
 * @param index 索引名
 * @param type mapping所对应的type
 */
public void addMapping(String index, String type) {
    try {
        // 使用XContentBuilder创建Mapping
        XContentBuilder builder = 
            XContentFactory.jsonBuilder()
                            .startObject()
                                .field("properties")
                                    .startObject()
                                        .field("name")
                                            .startObject()
                                                .field("index", "not_analyzed")
                                                .field("type", "string")
                                            .endObject()
                                        .field("age")
                                            .startObject()
                                                .field("index", "not_analyzed")
                                                .field("type", "integer")
                                            .endObject()
                                    .endObject()
                            .endObject();
        System.out.println(builder.string());           
        PutMappingRequest mappingRequest = Requests.putMappingRequest(index).source(builder).type(type);
                this.client.admin().indices().putMapping(mappingRequest).actionGet();
    } catch (ElasticsearchException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

3.1 删除索引

/**
 * 删除索引
 * @param index 要删除的索引名
 */
public void deleteIndex(String index) {
    DeleteIndexResponse deleteIndexResponse = 
        this.client
            .admin()
            .indices()
            .prepareDelete(index)
            .get();
    System.out.println(deleteIndexResponse.isAcknowledged()); // true表示成功
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. 文档CURD操作

增删改查是数据的基本操作,同时也是使用频率最高的一类操作。本小节介绍使用Java API来实现document的增删改查。

3.1 新增文档

/**
 * 创建一个文档
 * @param index index
 * @param type type
 */
public void createDoc(String index, String type) {

    try {
        // 使用XContentBuilder创建一个doc source
        XContentBuilder builder = 
            XContentFactory.jsonBuilder()
                            .startObject()
                                .field("name", "zhangsan")
                                .field("age", "lisi")
                            .endObject();

        IndexResponse indexResponse = this.client
                                        .prepareIndex()
                                        .setIndex(index)
                                        .setType(type)
                                        // .setId(id) // 如果没有设置id,则ES会自动生成一个id
                                        .setSource(builder.string())
                                        .get();
        System.out.println(indexResponse.isCreated());
    } catch (ElasticsearchException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3.2 更新文档

/**
 * 更新文档
 * @param index
 * @param type
 * @param id
 */
public void updateDoc(String index, String type, String id) {
    try {
        XContentBuilder builder = 
            XContentFactory.jsonBuilder()
                            .startObject()
                                .field("name", "lisi")
                                .field("age", 12)
                            .endObject();

        UpdateResponse updateResponse = 
            this.client
                .prepareUpdate()
                .setIndex(index)
                .setType(type)
                .setId(id)
                .setDoc(builder.string())
                .get();
        System.out.println(updateResponse.isCreated()); // true表示成功
    } catch (ElasticsearchException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

注意,id参数必须是确定存在的id值,否则会抛出document missing的异常。

3.3 查询文档

查询文档可以是根据id查询,也可以是根据复杂的查询条件查询。根据id的get查询代码如下。

/**
 * 根据ID查询一条数据记录。
 * @param id 要查询数据的ID。
 * @return 返回查询出来的记录对象的json字符串。
 */
public String get(String index, String type, String id) {
    GetResponse getResponse = this.client
                                .prepareGet()   // 准备进行get操作,此时还有真正地执行get操作。(与直接get的区别)
                                .setIndex(index)  // 要查询的
                                .setType(type)
                                .setId(id)
                                .get();
    return getResponse.getSourceAsString();
}
````

基于复杂查询条件的示例代码如下。





<div class="se-preview-section-delimiter"></div>

```java
/**
 * 使用filter方式查询数据。
 * @param index 数据所在的索引名
 * @param type 数据所在的type
 * @return 
 */
public List<String> queryByFilter(String index, String type) {

    // 查询名为zhangsan的数据
    FilterBuilder filterBuilder = FilterBuilders.termFilter("name", "zhangsan");
    SearchResponse searchResponse = 
        this.client
            .prepareSearch()  
            .setIndices(index)
            .setTypes(type)
            .setPostFilter(filterBuilder)
            .get();

    List<String> docList = new ArrayList<String>();
    SearchHits searchHits = searchResponse.getHits();
    for (SearchHit hit : searchHits) {
        docList.add(hit.getSourceAsString());
    }
    return docList;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

3.4 删除文档

下面的代码删除指定id的文档。

/**
 * 删除一条数据
 * @param index
 * @param type
 * @param id
 */
public void deleteDoc(String index, String type, String id) {
    DeleteResponse deleteResponse  = this.client
            .prepareDelete()  
            .setIndex(index)
            .setType(type)
            .setId(id)
            .get();
    System.out.println(deleteResponse.isFound()); // true表示成功
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

根据复杂的查询条件来删除文档。

/**
 * 根据查询条件删除文档。
 */
public void deleteByQuery(String index, String type) {
    try {
        QueryBuilder queryBuilder = QueryBuilders.termQuery("name", "zhangsan");
        DeleteByQueryResponse deleteByQueryResponse = this.client
                .prepareDeleteByQuery(index)
                .setTypes(type)
                .setQuery(queryBuilder)
                .get();
    } catch (ElasticsearchException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

4. 聚合操作

聚合操作的API稍微比较复杂一点,本文仅以min聚合的示例来说明聚合API的调用方式,其他的聚合API调用步骤类似。

/**
 * 使用min聚合查询某个字段上最小的值。
 * @param index
 * @param type
 */
public void min(String index, String type) {
    SearchResponse response = this.client
                            .prepareSearch(index)
                            .addAggregation(AggregationBuilders.min("min").field("age"))
                            .get();

    InternalMin min = response.getAggregations().get("min");
    System.out.println(min.getValue());
}
分享到:
评论

相关推荐

    项目实战——Spark将Hive表的数据写入ElasticSearch(Java版本)

    在本项目实战中,我们将探讨如何使用Java编程语言,结合Spark和Hive,将Hive中的数据高效地导入到ElasticSearch(ES)中,并利用ES的别名机制实现数据更新的平滑过渡。以下是对这个流程的详细解析: 1. **Hive数据...

    解密搜索引擎技术实战++Lucene&amp;Java;精华版_.pdf

    随着大数据时代的到来,单台服务器往往无法满足大规模数据的搜索需求,因此,理解如何使用Solr或Elasticsearch(基于Lucene的分布式搜索引擎)进行集群部署和管理,是提升搜索效率的关键。 除此之外,实战部分会...

    搜索引擎-java

    三、分布式搜索引擎——Solr与Elasticsearch 1. Apache Solr:Solr是基于Lucene构建的企业级搜索平台,支持分布式搜索、多字段排序、 faceted search等功能,广泛应用于电商、新闻门户等领域。Java开发者可以利用...

    人工智能-项目实践-搜索引擎-基于Nutch+ElasticSearch+MySQL+SSM的简易搜索引擎

    标题中的“人工智能-项目实践-搜索引擎-基于Nutch+ElasticSearch+MySQL+SSM的简易搜索引擎”揭示了一个项目,旨在构建一个简易的搜索引擎,利用了人工智能的一些原理和技术。这个项目结合了多个开源工具,包括Nutch...

    一款基于SQL查询ES的Java工具包,支持SQL解析DSL,支持JDBC驱动,支持和Mybatis、Spring集成.zip

    Elasticsearch是一个流行的开源搜索引擎和分析引擎,广泛应用于日志分析、实时分析等领域。这个工具包允许开发者使用他们熟悉的SQL语法来操作ES的数据,提高了开发效率。 描述中提到的“支持SQL解析DSL”意味着该...

    elasticsearch-7.4.2-linux-x86_64.tar.gz

    5. RESTful API:Elasticsearch 使用 RESTful 风格的 API 进行操作,使得与各种编程语言的集成变得简单,通过 HTTP 协议即可进行数据的增删改查和搜索操作。 6. 插件支持:Elasticsearch 社区提供了丰富的插件,...

    迅速搭建全文搜索平台——开源搜索引擎实战教程--代码.rar

    总的来说,这个实战教程将带你从零开始,通过实际操作,掌握开源搜索引擎Elasticsearch的使用,让你能够迅速搭建出自己的全文搜索平台。无论你是开发者还是系统管理员,都能从中受益,提升你的技术能力。现在就让...

    搜索引擎solr和elasticsearchJava开发J

    标题中的“搜索引擎solr和elasticsearchJava开发J”提到了两个关键的开源搜索技术——Apache Solr和Elasticsearch,以及它们与Java的结合使用。这两个都是基于Lucene库的全文检索引擎,广泛应用于大数据量的全文搜索...

    Elasticsearch实战与原理解析 源代码.zip

    Elasticsearch是一个开源的全文搜索引擎,它以分布式、RESTful接口和实时性为特点,广泛应用于数据搜索、分析和监控。这份"**Elasticsearch实战与原理解析 源代码**"的压缩包文件提供了关于这个强大工具的实践案例和...

    JSP源码——[搜索链接]淘特搜索引擎共享版_tot_search_engine.zip

    - 使用更先进的搜索引擎框架,如Elasticsearch,提升搜索性能。 - 采用分布式架构,应对高并发请求。 - 结合机器学习,实现个性化推荐。 总之,淘特搜索引擎共享版的JSP源码为我们提供了一个实践和学习的平台,通过...

    Mybatis的Mapper方式整合elasticsearch的DSL调用,基于接口和代理生成bean注入的方式进行调用

    而Elasticsearch(ES)则是一款强大的全文搜索引擎,常用于大数据分析和实时搜索。本篇文章将详细介绍如何将Mybatis的Mapper方式与Elasticsearch的DSL(Domain Specific Language)查询相结合,以及如何通过CGlib...

    PHP搜索引擎Sphinx使用教程.zip

    描述中的“JAVA有ElasticSearch搜索引擎,我们PHP也有”暗示了尽管Java有一个强大的全文搜索引擎Elasticsearch,PHP也有类似的功能强大的解决方案——Sphinx。这表明开发者可以在PHP环境中享受到类似于Java的全文搜索...

    Java搜索工具——Lucene实例总结(一)

    Java搜索工具——Lucene实例总结(一) Lucene是一个高性能、全文检索库,由Apache软件基金会开发并...在实际项目中,还可以结合其他工具,如Solr或Elasticsearch,构建分布式搜索引擎,以满足大规模数据的处理需求。

    计算机课程毕设:基于ElasticSearch+Spark 构建高相关性搜索服务&千人千面推荐系统.zip

    开发者需要理解ElasticSearch的数据模型,如文档、索引、类型等,并学会使用Java API或Elasticsearch RESTful接口进行数据的插入、更新和查询操作。此外,还需要对ElasticSearch的集群和分布式特性有深入理解,以便...

    粗通ElasticSearch

    ElasticSearch是一个基于Lucene构建的开源搜索引擎,它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。它能够快速和可扩展地存储、搜索和分析大量数据。ElasticSearch通常被用作底层引擎技术,...

    人工智能-项目实践-检索系统-基于 ElasticSearch 的文件检索系统

    Elasticsearch是一种强大的分布式搜索引擎,它提供了实时、可扩展的数据存储和搜索功能,非常适合用于搭建高效的检索系统。 首先,要启动这个项目,我们需要准备Elasticsearch运行环境。这包括下载Elasticsearch的...

    elasticsearch-8.0.1-linux-x86_64.tar.gz

    1. **数据导入**:可以使用`curl`命令或客户端库(如Java API)将JSON数据导入到Elasticsearch索引。 2. **查询**:Elasticsearch提供了一种强大的查询语言——Query DSL,支持丰富的查询语法,包括布尔查询、范围...

    elasticsearch-analysis-ik-7.10.0.zip

    Elasticsearch(ES)作为一款强大的开源搜索引擎,广泛应用于日志分析、数据挖掘和信息检索等领域。在处理中文数据时,准确的分词是至关重要的,这时就需要借助于专门的中文分词器。"elasticsearch-analysis-ik-...

    elasticsearch-6.8.7.tar.gz

    Elasticsearch 6.8.7 是一个高度可扩展的开源全文搜索引擎,它设计用于提供快速、近实时的搜索和分析能力。这个压缩包“elasticsearch-6.8.7.tar.gz”包含了运行Elasticsearch 6.8.7所需的所有文件。Elasticsearch...

    decouverte-utilisation-elasticsearch.pdf

    Elasticsearch,有时被简称为“ES”,是目前最受欢迎的日志分析平台——ELK Stack(Elasticsearch、Logstash 和 Kibana)的核心组件。本文旨在为新用户提供必要的知识和工具,帮助他们开启Elasticsearch之旅。 ####...

Global site tag (gtag.js) - Google Analytics