美文网首页
Elastic 从安装到入门的使用(python3,spring

Elastic 从安装到入门的使用(python3,spring

作者: jandy_6838 | 来源:发表于2021-02-04 15:43 被阅读0次

    一、概要说明

    本篇记载了从安装elastic search 数据库 (以下简称ES),到使用python操作使用ES(主要是批量新增数据),

    使用java spring boot 从ES中检索数据,及ES数据库客户端工具kibana的简单使用。

    感觉ES版本更新频率还是挺高了,最难的是不同版本差异点。

    大概从2021年1月开始正式接触使用 ES,这个时候ES版本是:7.10.2 版本。

    下载安装的版本,我选择前一个版本:7.10.1

    二、安装方面

    安装的系统在ubuntu上

    1、安装es:

       1、解压目录后,进入目录后,调整配置

    tar -xzvf elasticsearch-7.10.1-linux-x86_64.tar.gz

    cd elasticsearch-7.10.1/config/ 

    2、vim elasticsearch.yml 添加配置  (启用密码)

    http.cors.enabled: true

    http.cors.allow-origin: "*"

    http.cors.allow-headers: Authorization

    xpack.security.enabled: true

    xpack.security.transport.ssl.enabled: true

    3、设置初始密码, 退出config目录,进入目录bin目录,执行程序

    ./elasticsearch-setup-passwords

    后会显示交互界面,输入多次密码

    Initiating the setup of passwords for reserved users elastic,kibana,logstash_system,beats_system.

    You will be prompted to enter passwords as the process progresses.

    Please confirm that you would like to continue [y/N]y

    Enter password for [elastic]:

    Reenter password for [elastic]:

    Enter password for [kibana]:

    Reenter password for [kibana]:

    Enter password for [logstash_system]:

    Reenter password for [logstash_system]:

    Enter password for [beats_system]:

    Reenter password for [beats_system]:

    Changed password for user [kibana]

    Changed password for user [logstash_system]

    Changed password for user [beats_system]

    Changed password for user [elastic]

    4、修改/etc/sysctl.conf文件,增加配置:vm.max_map_count=262144

    vi /etc/sysctl.conf

    sysctl -p

    5、接下来执行启动

    //直接启动ElasticSearch

    ./elasticsearch  

    //或者使用后台方式进行启动

    ./elasticsearch -d

    访问 http://192.168.XX.XX:9200  检查安装情况


    2、安装kibana

    1、解压压缩包

    tar -zxvf kibana-7.10.1-linux-x86_64

    cd kibana-7.10.1-linux-x86_64/

    2、进入config目录,vi 编辑 kibana.yml配置文件,主要配置如下:

    server.host: "0.0.0.0"  # 允许外网访问

    elasticsearch.username: "elastic"  #es用户名

     elasticsearch.password: "passoword123"  #es的密码

    3、后台方式启动,退出config目录,到bin 目录

    ./kibana &    后台启动

    访问http:// 192.168.xx.XX:5061  输入用户密码检查安装情况

    三、python 操作ES

    通过python把数据处理保存进ES数据库

    需pip 安装相应包:

    pip install elasticsearch==7.5.1

    建立数据库访问操控类:


    import json

    from elasticsearch import Elasticsearch

    from elasticsearch import helpers

    class ElasticDB():

        def __init__(self,hosts=["192.168.XX.XX"],username="elastic",password="password123"):

            try:

              # 创建普通类型的ES客户端

              self.es  = Elasticsearch(hosts, http_auth=(username, password))

              if not self.es.ping():

                  raise Exception("连接es数据库失败,请检查IP或端口!")

            except Exception as e:

                raise Exception(f"连接es数据库出现异常{e}")

        def __del__(self):

            if self.es is not None:

                self.es=None

        # 批量插入数据内容

        def insertBatchData(self, dataList):

            # res = self.es.bulk(index=indexName,doc_type=docType, body=dataList, raise_on_error=True)

            res = helpers.bulk(self.es, dataList)

            return res

       ....


    逻辑处理从mongdb中批量取数据处出来,批量插入es数据库(代码片段):

                outList=self.mongoDB.getBatchDataByIdList(idLists) # 从mongodb中批量取出数据

                esList=[]

                errorList=[]

                for doc in outList:

                    esDo=self._mongoToEsParser(doc)  # 逐个文档转换成 es 的新dict格式的数据

                    if esDo is not None:

                        # 拼接插入数据结构

                        action = {

                            "_index":self.indexName,  #设置es索引名

                            # "_type": self.docType,  #不设置es type 使用默认的

                            "_id":doc['_id'],  # 手动设置es 的id字段值,

                            "_source":esDo  # 设置文档主要数据体内容

                        }

                        esList.append(action)

                    else:

                        errorList.append(doc['_id'])

                end1 = time.time()

                self.log.info(f'转换成es数据: {len(esList)}/{curSize} ---》耗时 {int(end1 - start)} 秒')

                out=self.esDB.insertBatchData(dataList=esList) # es 执行数据的批量插入

                # print(out)

                end2 = time.time()

                self.log.info(f'执行es: {len(esList)}条数据的插入, 结果:{out}---》耗时 {int(end2 - end1)} 秒')


    四、java - spring boot  操作检索ES 数据库

    1、版本需对应好:

    官方说明

    2、pom.xml 配置,及连接配置

    版本:

    <parent>

     <groupId>org.springframework.boot</groupId> 

     <artifactId>spring-boot-starter-parent</artifactId> 

     <version>2.4.2</version> 

    </parent>

    主要依赖:

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>

    </dependency>

    application.properties 的配置:

    spring.elasticsearch.rest.uris=192.168.1.XXX:9200

    spring.elasticsearch.rest.username=elastic

    spring.elasticsearch.rest.password=password123

    spring.elasticsearch.rest.connection-timeout=10s

    spring.elasticsearch.rest.read-timeout=30s

    3、 关键代码篇段

    controller 层关键代码:


    @RestController

    @RequestMapping("v100/es")

    @Validated

    @Slf4j

    public class EsSearchPatentBiControl {

        @Autowired

        private RestHighLevelClient client; //官方建议使用的方式,以前9300端口操作es底层将不支持了

        /**

        * 组合检索  数据信息

        * 多字段匹配组合

        * @return

        */

    //    @LoginRequired

        @PostMapping("/multi_query")

        public ResultVO multiQueryAbsData(EsDTO esDTO) {

            long start=System.currentTimeMillis();

            if (esDTO==null) {

                log.error("检索的信息参数不能为空!");

                return ResultVO.getFailResult("检索的信息参数不能为空!");

            }

            try {

                SearchRequest request = new SearchRequest("index_name_*");//设置索引值,多个索引可以用*通配

                QueryBuilder query = QueryBuilders.matchAllQuery();

                List<QueryBuilder> listMustQuery=esDTO.getListMust();// 获取组合的must查询条件

                List<QueryBuilder> listFilterQuery=esDTO.getListFilter();// 获取组合的filter查询条件

                BoolQueryBuilder queryBool=null;

                if(listMustQuery.size()>0)

                {

                    queryBool = QueryBuilders.boolQuery();

                    for(QueryBuilder subQuery:listMustQuery){

                        queryBool=queryBool.must(subQuery);

                    }

                }

                if(listFilterQuery.size()>0){

                    if(queryBool==null){

                        queryBool=QueryBuilders.boolQuery();

                    }

                    for(QueryBuilder subQuery:listFilterQuery){

                        queryBool=queryBool.filter(subQuery);

                    }

                }

                if (queryBool!=null){

                    query=queryBool;

                }

                log.info("查询语句:{}",query.toString());

                EsPageVO esPageVO = ElasticsearchUtil.searchDataPage(client, request, esDTO.getCurrentPage()-1, esDTO.getPageSize(), query, "", "");

                return ResultVO.getSuccessResult(esPageVO);

            }catch (IOException ioe){

                log.error("获取文档IO异常: ", ioe);

                return  ResultVO.getFailResult("获取文档IO异常: "+ ioe);

            }finally {

                long end=System.currentTimeMillis();

                Long useTime=(end-start)/1000;

                log.info("执行组合查询:总共耗时[{}]秒",useTime);

            }

        }

    }


    Es工具类代码:


    @Slf4j

    public class ElasticsearchUtil {

    //    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchUtil.class);

    /**

        * 使用分词查询,并分页

        * @param client    查询客户端

        * @param searchRequest          查询request

        * @param startPage      当前页

        * @param pageSize      每页显示条数

        * @param query          查询条件

        * @param sortField      排序字段

        * @param highlightField 高亮字段

        * @return

        */

        public static EsPageVO searchDataPage(RestHighLevelClient client,SearchRequest searchRequest,

    int startPage,int pageSize, QueryBuilder query, String sortField, String highlightField)throws IOException {

    SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();

    //排序字段

            if (Strings.isNotEmpty(sortField)) {

    sourceBuilder.sort(sortField, SortOrder.DESC);

    }

    // 高亮设置一个字段

            if (Strings.isNotEmpty(highlightField)) {

    HighlightBuilder highlightBuilder =new HighlightBuilder();

    highlightBuilder.preTags("<span style='color:red' >");//设置前缀

                highlightBuilder.postTags("</span>");//设置后缀

                // 设置高亮字段

                highlightBuilder.field(highlightField);

    sourceBuilder.highlighter(highlightBuilder);

    }

    //searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());

            sourceBuilder.query(query);

    //分页设置

            sourceBuilder.from(startPage);

    sourceBuilder.size(pageSize);

    // 设置是否按查询匹配度排序

            sourceBuilder.explain(true);

    sourceBuilder.trackTotalHits(true);

    sourceBuilder.fetchSource(null,new String[]{"create_time","update_count","source_id"});

    searchRequest.source(sourceBuilder);

    //        searchRequest.searchType(SearchType.QUERY_THEN_FETCH);

            // 执行搜索,返回搜索响应信息

            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

    long totalHits = searchResponse.getHits().getTotalHits().value;

    long length = searchResponse.getHits().getHits().length;

    log.info("共查询到[{}]条数据,处理的分页条数[{}]", totalHits, length);

    if (searchResponse.status().getStatus() ==200) {

    // 解析对象

                List> sourceList =setSearchResponse(searchResponse, highlightField);

    return new EsPageVO(startPage, pageSize, (int) totalHits, sourceList);

    }

    return null;

    }

    /**

        * 高亮结果集 特殊处理

        *

        * @param searchResponse

        * @param highlightField

        */

        private static List> setSearchResponse(SearchResponse searchResponse, String highlightField) {

    List> sourceList =new ArrayList>();

    StringBuffer stringBuffer =new StringBuffer();

    for (SearchHit searchHit : searchResponse.getHits().getHits()) {

    searchHit.getSourceAsMap().put("id", searchHit.getId());

    if (Strings.isNotEmpty(highlightField)) {

    //                System.out.println("遍历 高亮结果集,覆盖 正常结果集" + searchHit.getSourceAsMap());

                    Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments();

    if (text !=null) {

    for (Text str : text) {

    stringBuffer.append(str.string());

    }

    //遍历 高亮结果集,覆盖 正常结果集

                        searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString());

    }

    }

    sourceList.add(searchHit.getSourceAsMap());

    }

    return sourceList;

    }

    }


    输出的分页类代码:


    @Data

    @ToString

    public class EsPageVO {

    /**

        * 当前页

        */

        private int currentPage;

    /**

        * 每页显示多少条

        */

        private int pageSize;

    /**

        * 总记录数

        */

        private int recordCount;

    /**

        * 本页的数据列表

        */

        private List>recordList;

    /**

        * 总页数

        */

        private int pageCount;

    /**

        * 只接受前4个必要的属性,会自动的计算出其他3个属性的值

        *

        * @param currentPage

        * @param pageSize

        * @param recordCount

        * @param recordList

        */

        public EsPageVO(int currentPage,int pageSize,int recordCount, List> recordList) {

    this.currentPage = currentPage+1;

    this.pageSize = pageSize;

    this.recordCount = recordCount;

    this.recordList = recordList;

    // 计算总页码

            pageCount = (recordCount + pageSize -1) / pageSize;

    }

    }


    检索的DTO类代码:


    @Data

    @NoArgsConstructor

    @AllArgsConstructor

    public class EsDTO {

        @ApiModelProperty("编号号")

        private String code;

        @ApiModelProperty("国家(值为:CN,JP,US..)")

        private String country;

        @ApiModelProperty("发行日期-起始时间")

        private String publicDateStart;

        @ApiModelProperty("公开日期-结束时间")

        private String publicDateEnd;

        @ApiModelProperty("种类编码")

        private String kindCode;

        @ApiModelProperty("标题")

        private String title;

        @ApiModelProperty("摘要")

        private String abs;

        /**

        * 当前页

        */

        @ApiModelProperty(value = "当前页", required=true)

        private int currentPage=1;

        /**

        * 每页显示多少条

        */

        @ApiModelProperty(value = "分页条数",required = true)

        private int pageSize=20;

        @ApiModelProperty(hidden = true)

        public List<QueryBuilder> getListMust(){

            List<QueryBuilder> listQuery=new ArrayList<>();

            if (Strings.isNotBlank(title)){

                listQuery.add(QueryBuilders.matchPhraseQuery("title",title));

            }

            if (Strings.isNotBlank(abs)) {

                listQuery.add(QueryBuilders.matchPhraseQuery("abstract",abs));

            }

            return listQuery;

        }

        public List<QueryBuilder> getListFilter(){

            List<QueryBuilder> listQuery=new ArrayList<>();

            if (Strings.isNotBlank(code)){

                listQuery.add(QueryBuilders.matchPhraseQuery("p_code",code));

            }

            if (Strings.isNotBlank(country)){

                listQuery.add(QueryBuilders.matchPhraseQuery("p_country",country));

            }

            if (Strings.isNotBlank(publicDateStart)) {

                listQuery.add(QueryBuilders.rangeQuery("p_date").gte(publicDateStart));

            }

            if (Strings.isNotBlank(publicDateEnd)) {

                listQuery.add(QueryBuilders.rangeQuery("p_date").lte(publicDateEnd));

            }

            if (Strings.isNotBlank(kindCode)){

                listQuery.add(QueryBuilders.matchPhraseQuery("kind_code",kindCode));

            }

            return listQuery;

        }

    }

    五、kibana的使用

    作为经常跟传统数据库打交道的开发人员,最希望还是有一个称手的 数据库客户端工具。

    对于ES来说,就是kibana .   这个工具给我感觉,还是不那么熟悉,(版本也一样差异大),

    我相信它的定位,还不是简单只是数据库客户端工具。。。

    入门者的我,先简单使用吧。

    在主菜单下:Home  -》 ManageMent -->Dev Tools .

    点开,左右格局的查询与结果展示。

    以下贴一两个常用命令(更多请,细细品读官网吧):

    1、简单查询单个匹配的:

    GET /index_name_xx/_search

    {

     "query": {

        "match": { "public_number": "3821464B"}

     }

    }

    2、查询总数据量

    GET /index_name_xx/_search

    {

      "track_total_hits": true,

      "query": {

        "match_all": {}

      }

    }

    3、查询重复的数据

    GET /index_name_xx/_search

    {

           "from": 0,

           "size": 0,

           "aggs": {

             "my":{

               "terms":{

                 "field": "public_number.keyword"

               }

             }

           }

    }

    4、组合查询

    GET index_name_XX_*/_search

    {

      "query": {

        "bool": {

          "must": [

            {"match_phrase": { "in_name":"张三" }},

            {"match_phrase": { "co_name": "XX公司"}}

          ],

          "filter":[

            {"match_phrase":{"p_country":"CN"}},

            {"range":{"create_date":{"gte":"20181024"}}}

            ]

        }

      }

    }

    相关文章

      网友评论

          本文标题:Elastic 从安装到入门的使用(python3,spring

          本文链接:https://www.haomeiwen.com/subject/kxebtltx.html