首页 > 数据库 >WM_技术中台下终搜的技术解决方案-stage1 mysql->logstash->es 数据采集并处理 暂时没用

WM_技术中台下终搜的技术解决方案-stage1 mysql->logstash->es 数据采集并处理 暂时没用

时间:2023-05-15 22:55:23浏览次数:44  
标签:product jdbc WM sql 查询 port mysql stage1 logstash

1 技术中台与终搜介绍 1.1 技术中台与终搜介绍 中台产生的背景 中台(技术、 业务、数据)最早是阿里巴巴提出来的。 2015年阿里 进行过一次架构调整,将搜索事业部、共享业务平台、数据技术及产品部组成了中台事业 群。 并喊出“小前台,大中台”的管理模式。 什么是中台 中台是介于前台和后台中间的平台(基础中间件),有点像编程时的适配层,起到承上启下的作用。当组 织架构太深了,前台后台隔得太远,沟通成本太高时,通过中台可以一定程度上来解决这个问题。 为什么使用中台 中台强调资源整合、能力沉淀,把一些公共、底层的算法和能力抽象出来,形成各种平台,供其他各个前 台进行调用, 什么是终搜 终搜平台是技术中台的一种体现;比如统一OSS,自动化配置、统一监控、统一登录平台、CICD&一站式 终搜平台都是技术中台的实现。 1.2 技术架构介绍  

 

 

    1.3 技术栈介绍

 

 

    服务(应用)名称 Docker容器地址 端口 查询服务 172.188.0.33 8888 分析服务 172.188.0.34 5555 网关服务 172.188.0.22 6666 logstash 172.188.0.77 9600 kinana 172.188.0.66 5601 msyql 172.188.0.15 3306 nacos1 nacos:8848 8848-->8848 nacos2 nacos:8848 8848-->8849 nacos3 nacos:8848 8848-->8850 nacos-server-mysql mysql:3306 3306 prometheus 172.188.0.11 9090 grafana 172.188.0.12 3000 eNode1 172.188.0.88 9200 / 9700 eNode2 172.188.0.89 9201 / 9800 eNode3 172.188.0.90 9202 / 9900 日志埋点与落盘 172.188.0.77 TCP 4567 链路追踪 172.188.0.99 9411 2 数据收集引擎之Logstash数据同步 2.1 数据收集引擎概述 logstash-input-jdbc logstash官方插件 logstash-input-jdbc集成在logstash(5.X之后)中,通过配置文件实现mysql与 elasticsearch数据同步 能实现mysql数据全量和增量的数据同步,且能实现定时同步. 2.2 Logstash数据同步与转换     2.2.1 全量同步 全量同步是指全部将数据同步到es,通常是刚建立es,第一次同步时使用。 tips 上传mysql-connector-java-5.1.48.jar 1、修改logstash.conf文件 目录切换 stdin从标准输入读取事件。 默认情况下,每一行读取为一个事件 什么是logstash 简单来说logstash就是一个具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输 出端;与此同时这根管道还可以根据自己的需求在inuput --out中间加上滤网,Logstash内置了几十种插 件,可以满足你的各种应用场景。 cd /usr/local/logstash/config/conf.d input { stdin {} #使用jdbc插件 jdbc { # mysql数据库驱动 #jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql connector-java-5.1.48.jar" jdbc_driver_class => "com.mysql.jdbc.Driver" # mysql数据库链接,数据库名 jdbc_connection_string => "jdbc:mysql://172.188.0.15:3306/product? characterEncoding=UTF-8&useSSL=false" # mysql数据库用户名,密码 jdbc_user => "root" jdbc_password => "root"     2、/usr/local/logstash/confifig/conf.d/sql目录修改full_jdbc.sql文件 full_jdbc内容如下 3、打开Kibana创建索引和映射 坑 mysql---logstash---es 如果创建的映射是有大写的时候,es会自动转成小写 而且查看映射数据结构的时候会出现两个相同的字段(productname和productName) # 分页 jdbc_paging_enabled => "true" # 分页大小 jdbc_page_size => "50000" # sql语句执行文件,也可直接使用 statement => 'select * from t' statement_filepath => "/usr/share/logstash/pipeline/sql/full_jdbc.sql" #statement => " select * from product where id <=100 " } } # 过滤部分( 不是必须项) filter { json { so urce => "message" remove_field => ["message"] } } # 输出部分 output { elasticsearch { # elasticsearch索引名 index => "product" # elasticsearch的ip和端口号 hosts => ["172.188.0.88:9200","172.188.0.89:9201","172.188.0.90:9202"] # 同步mysql中数据id作为elasticsearch中文档id document_id => "%{id}" } stdout { codec => json_lines } } cd /usr/local/logstash/config/conf.d/sql vi full_jdbc.sql SELECT id, TRIM( REPLACE ( product_name, ' ', '' ) ) AS productname, price FROM product     这样就导致我们自己定义的映射无法使用,而有数据的是es自动生成的那个小写 4、查询索引以及数据 如果对映射没有硬性要求,可以忽略当前步骤,会自动创建索引 上图显示无数据;"value" : 0表示命中0条 5、重启logstash进行全量同步 报错信息 原因为:在启动fifirewalld之后,iptables被激活, 此时没有docker chain,重启docker后被加入到iptable里面 PUT product { "settings": { "number_of_shards": 1, "number_of_replicas": 1 }, "mappings": { "properti es ": { "productname": { "t ype": "text" }, "p rice": { "type": "double" } } } } GET product/_search docker restart 82b89c39282a     解决方案 查看日志 6、再次查看索引以及数据 Error response from daemon: Cannot restart container 3849f947e115: driver failed programming external connectivity on endpoint logstash (60f5d9678218dc8d19bc8858fb1a195f4ebee294cff23d499a28612019a0ff78): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 4567 -j DNAT -- to-destination 172.188.0.77:4567 ! -i br-413b460a0fc8: iptables: No chain/target/match by that name. systemctl restart docker docker logs -f --tail=200 82b89c39282a http://172.17.0.225:9200/_cat/count/product?v     7、遇到的问题 查看空间大小 解决方案一: 解决方案二 找cf94b7124ef90b9ea6a2a9c48494bd307661829daa245320a408fc392370fb14-json.log 路径是 /var/lib/docker/containers/cf94b7124ef90b9ea6a2a9c48494bd307661829daa245320a408fc39 2370fb14 es集群数据量增速过快,如果磁盘空间过小;会导致个别es node节点磁盘使用率在%90以上 ,由于ES新节 点的数据目录data存储空间不足,导致从master主节点接收同步数据的时候失败,此时ES集群为了保护数 据,会自动把索引分片index置为只读read-only. 到达85的时候 ;就停止导入,不停重试..... df -h PUT _settings { "index": { "blocks": { "read_only_allow_delete": "false" } } } find / -type f -size +2000M     使用黑洞设置为空 2.2.2 增量同步 增量同步是指将后续的更新、插入记录同步到es。 1、修改增量配置 修改上面的logstash.conf文件 cat /dev/null > cf94b7124ef90 b 9 ea6a2a9c48494bd307661829daa245320a408fc392370fb14-json.log input { stdin {} #使用jdbc插件 jdbc { # mysql数据库驱动 #jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql connector-java-5.1.48.jar" jdbc_driver_class => "com.mysql.jdbc.Driver" # mysql数据库链接,数据库名 jdbc_connection_string => "jdbc:mysql://172.188.0.15:3306/product? characterEncoding=UTF-8&useSSL=false" # mysql数据库用户名,密码 jdbc_user => "root" jdbc_password => "root" # 设置监听间隔 各字段含义(分、时、天、月、年),全部为*默认含义为每分钟更新一次 # /2* * * *表示每隔2分钟执行一次,依次类推 schedule => "* * * * *" # 分页 jdbc_paging_enabled => "true" # 分页大小 jdbc_page_size => "50000" # sql语句执行文件,也可直接使用 statement => 'select * from t' statement_filepath => "/usr/share/logstash/pipeline/sql/increment_jdbc.sql" #上一个sql_last_value值的存放文件路径, 必须要在文件中指定字段的初始值 #last_run_metadata_path => "./config/station_parameter.txt" #设置时区,此处更新sql_last_value查询的时区,sql_last_value还是默认UTC jdbc_default_timezone => "Asia/Shanghai" #使用其它字段追踪,而不是用时间 #use_column_value => true #追踪的字段 #tracking_column => id tracking_column_type => "timestamp" }     2、/usr/local/logstash/confifig/conf.d/sql目录下新建increment_jdbc.sql文件 increment_jdbc.sql内容如下 此处sql尽量保持与全量一致Select后的 4、重启容器 上述步骤完成后重启容器 5、查看之前的数据 } # 过滤部分(不是必须项) filter { json { source => "message" remove_field => ["message"] } } # 输出部分 output { elas t i c s ea rc h { # e l a st ic se arch索引名 index => "product" # elasticsearch的ip和端口号 hosts => ["172.188.0.88:9200","172.188.0.89:9201","172.188.0.90:9202"] # 同步mysql中数据id作为elasticsearch中文档id document_id => "%{id}" } stdout { codec => json_lines } } cd /usr/local/logstash/config/conf.d/sql vi increment_jdbc.sql SELECT id, TRIM( REPLACE ( product_name, ' ', '' ) ) AS productname, price FROM product where update_time > :sql_last_value # 启动 docker restart 容器id     6、在数据库中插入数据 7、查看logstash运行日志 稍等片刻 8、查看es数据 9、同步原理 last_run_metadata_path=>"/usr/share/logstash/.logstash_jdbc_last_run" 在容器里面的/usr/share/logstash/路径下的隐藏文件.logstash_jdbc_last_run中记录了全量同步的 UTC时间 坑: 如果你的数据库使用了mycat分库分表,当前的方案是有问题的,可以使用其他方案代替 因为:Logstah通过你设置的分页执行业务sql,在业务sql中,logstash对sql语句进行了包装 (为了分页;套了一层);count前面加了反斜杠,在mysql中是不识别的 替代方案,可以使用自动追踪(不走分页): use_column_value => true 追踪的字段 tracking_column => updatetime 追踪的类型 http://172.17.0.225:9200/_cat/count/product?v INSERT INTO ` p ro du c t ` ( ` i d ` , ` p ro d uct_name`, `price`) VALUES('12196 0 0 00 ' , 't es t 0 0 1 ' ,1 0 0 ) ; INSERT INT O `product` (`id`, `product_name`, `price`) VALUES('121260001','test002',300); docker logs -f --tail=100 容器id http://172.17.0.225:9200/_cat/count/product_list_info?v #进入容器 docker exec -it 4f95a47f12de /bin/bash #查看记录点 cat /usr/share/logstash/.logstash_jdbc_last_run     tracking_column_type => "timestamp" 第一次在logstash_jdbc_last_run维护下时间 Logstash每次通过updatetime作为查询条件查询,然后将最大的日期写入到 logstash_jdbc_last_run 这里的日期和上面不一样,上面分页的日期是调度开始的时间,这里的时间是业务数据库的时间 每次同步完成记录该时间(重要) 注意 logstash_jdbc_last_run默认是没有的,执行增量后创建 文件也是可以删除的 容器重启会自动创建 3 电商平台全文检索与分词技术 3.1 电商平台全文检索 需求 京东搜索【华为全面屏】,搜索结果包含了华为各个产品线的数据【手机】【全面屏手机】【手机贴膜】 【华为笔记本】【华为电视】等等...     搜索结果(手机)       搜索结果(钢化膜) 搜索结果(笔记本、电视) 全面屏实现目标 模拟京东的全文检索 , 实 现 以 下 几 个 维度 1、通过关键字进行 全 文 匹 配 产 品 搜 索 2、从海量数据 中索取数据做到近实时 3、获取全部 产品实现分页逻辑 4、检索后的产品进行关键字高亮显示 5、高度具象,抽取出开放API 3.2 传统实现方式 1、MySql的实现方式 查询包含【华为全面屏】的所有数据 不考虑多个like语句进行union操作 效率太低无法使用 查询结果 GET /_analyze { "analyzer": "ik_smart", "text": "网红蓝瘦香菇喊麦全面屏" } SELECT id, trim( REPLACE ( product_name, ' ', '' ) ) AS productname, price, trim( REPLACE ( store_name, ' ', '' ) ) AS storename, eval_count AS evalcount, purchase_index AS purchaseindex, trim( REPLACE ( store_type, ' ', '' ) ) AS storetype, trim( REPLACE ( sku, ' ', '' ) ) AS sku, trim( REPLACE ( one_level_category, ' ', '' ) ) AS onelevel, trim( REPLACE ( two_level_category, ' ', '' ) ) AS twolevel, trim( REPLACE ( three_level_category, ' ', '' ) ) AS threelevel, trim( REPLACE ( four_level_category, ' ', '' ) ) AS fourlevel, update_time AS updatetime FROM product_list WHERE product_name LIKE '%华为全面屏%' LIMIT 0,10000     3.3 分布式框架集成 版本说明: Spring Cloud 集成Spring Cloud aɹ ibaba https://github.com/alibaba/spring-cloud alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E     3.4 终搜平台实现方式 1)配置编写与全文检索编写 1、Es高阶客户端连接Elasticsearch: package com.itheima.config; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Class: ElasticsearchConfig * @Package com.itheima.config * @Description: 配置类:构建Elasticsearch客户端连接配置 * @Company: http://www.itheima.com/ */ @Configuration @ConfigurationProperties(prefix = "elasticsearch") public class ElasticsearchConfig { //es集群ip private String cluster_host; //es集群节点一端口     private Integer eNode1_port; //es集群节点二端口 private Integer eNode2_port; //es集群节点三端口 private Integer eNode3_port; /** * 超时时间设为5分钟 */ private static final int TIME_OUT = 5 * 60 * 1000; /* * @Descr iption: * @Me t h od : Es高阶客户端构建器 * @Pa ra m : * @ U pd a t e : * @ si n c e : 1.0.0 * @Return: * */ @Bean public RestClientBuilder restClientBuilder() { return RestClient.builder( new HttpHost(cluster_host, eNode1_port, "http"), new HttpHost(cluster_host, eNode2_port, "http"), new HttpHost(cluster_host, eNode3_port, "http")); } /* * @Description: 构建Es高阶客户端 * @Method: highLevelClient * @Param: [restClientBuilder] * @Update: * @since: 1.0.0 * @Return: org.elasticsearch.client.RestHighLevelClient * */ @Bean(destroyMethod = "close") public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) { restClientBuilder.setRequestConfigCallback( new RestClientBuilder.RequestConfigCallback() { @Override public RequestConfig.Builder customizeRequestConfig( RequestConfig.Builder requestConfigBuilder) { return requestConfigBuilder.setSocketTimeout(TIME_OUT); } }); return new RestHighLevelClient(restClientBuilder); } public String getCluster_host() { return cluster_host; } public void setCluster_host(String cluster_host) { this.cluster_host = cluster_host;     全文检索代码编写: 1、编写全文检索接口 } public Integer geteNode1_port() { return eNode1_port; } public void seteNode1_port(Integer eNode1_port) { this.eNode1_port = eNode1_port; } public In teger geteNode2_port() { re turn eNode2_port; } publ ic void seteNode2_port(Integer eNode2_port) { this.eNode2_port = eNode2_port; } public Integer geteNode3_port() { return eNode3_port; } public void seteNode3_port(Integer eNode3_port) { this.eNode3_port = eNode3_port; } } package com.itheima.service; import com.itheima.commons.pojo.CommonEntity; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchHit; import java.util.List; import java.util.Map; /** * @Class: ElasticsearchDocumentService * @Package com.itheima.service * @Description: 文档操作接口 * @Company: http://www.itheima.com/ */ public interface ElasticsearchDocumentService { //全文检索 public SearchResponse matchQuery(CommonEntity commonEntity) throws Exception; }     2、编写全文检索实现 /* * @Descr i p t i o n : 全 文 检 索 * 使用mat c h Q u e r y 在 执 行 查 询时,搜索的词会被分词器分词 * @Method: searchMatch * @Pa ra m : [indexName, key, value] * @U pd a te : * @ s i nc e : 1 .0 .0 * @ R e t u rn : o rg .elasticsearch.search.SearchHit[] * */ public SearchResponse matchQuery(CommonEntity commonEntity) throws Exception { //构建查询响应 SearchResponse response = null; //构建查询请求用来完成和搜索文档,聚合,建议等相关的任何操作同时也提供了各种方式来完成 对查询结果的高亮操作。 SearchRequest searchRequest = new SearchRequest(commonEntity.getIndexName()); //构建DSL请求体;trackTotalHits如果不设置true,查询数据最大值还是10000 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true); //获取前端的查询条件(Map查询条件) getClientConditions(commonEntity, searchSourceBuilder); //高亮设置 searchSourceBuilder.highlighter(SearchTools.getHighlightBuilder(commonEntity.ge tHighlight())); //前端页码 int pageNumber = commonEntity.getPageNumber(); //前端每页数量 int pageSize = commonEntity.getPageSize(); //计算查询的下标 int dest = (pageNumber - 1) * pageSize; searchSourceBuilder.from(dest); //每页数量 searchSourceBuilder.size(pageSize); //查询条件对象放入请求对象中 searchRequest.source(searchSourceBuilder); //方法执行开始时间 long startTime = System.currentTimeMillis(); System.out.println("开始Elasticsearch查询..."); //执行远程查询 response = client.search(searchRequest, RequestOptions.DEFAULT); //计算远程查询耗时 System.out.println("结束Elasticsearch查询总耗时:" + (System.currentTimeMillis() - startTime) + "毫秒"); //处理高亮 SearchTools.setHighResultForCleintUI(response, commonEntity.getHighlight()); return response;     3、编写控制器 } @RestController @RequestMappi n g ( "v 1/ d o cs ") public class E la s ti c s ea rc hDocController { private static final Logger logger = LoggerFactory .g e tLogger(ElasticsearchDocController.class); @Aut o wi r ed Elas t i c searchDocumentService elasticsearchDocumentService; /* * @Description: 全文检索 * @Method: matchQuery * @Param: [commonEntity] * @Update: * @since: 1.0.0 * @Return: com.itheima.commons.result.ResponseData * */ @GetMapping(value = "/mquery") public ResponseData matchQuery(@RequestBody CommonEntity commonEntity) { // 构造返回数据 ResponseData rData = new ResponseData(); //批量查询返回结果 SearchResponse result = null; try { //通过高阶API调用批量新增操作方法 result = elasticsearchDocumentService.matchQuery(commonEntity); //查询数量除以每页数量 等于合计分页数量 long aSize = result.getHits().getTotalHits().value; logger.info("总数据量:" + aSize + "条"); int cSize = result.getHits().getHits().length; logger.info("当前获取数据:" + cSize + "条"); //通过类型推断自动装箱(多个参数取交集) rData.setResultEnum(result.getHits().getHits(), ResultEnum.success, Integer.valueOf(String.valueOf(aSize))); //日志记录 logger.info(TipsEnum.batch_get_doc_success.getMessage()); } catch (Exception e) { //打印到控制台 e.printStackTrace(); //日志记录 logger.error(TipsEnum.batch_get_doc_fail.getMessage()); //构建错误返回信息 rData.setResultEnum(ResultEnum.error); } return rData; } }     4、配置文件编写 service-elasticsearch-dev.yml bootstrap.yml server-addr: C:\Users\My\nacos\confifig 2) 服务网关路由全局配置 http://172.17.0.225:8848/nacos/ server: port: 8888 spring: sleuth: sampler: pr o bability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1 zipkin : base-url: http://172.17.0.225:9411/ # 指定了 Zipkin 服务器的地址 cloud: nacos: discovery: server-addr: 172.17.0.225:8848,172.17.0.225:8849,172.17.0.225:8850 elasticsearch: cluster_host: 172.17.0.225 eNode1_port: 9200 eNode2_port: 9201 eNode3_port: 9202 spring: application: name: service-elasticsearch #微服务名称,对应dataId profiles: active: dev cloud: nacos: config: #配置中心服务地址 server-addr: 172.17.0.225:8848,172.17.0.225:8849,172.17.0.225:8850 #配置中心文件类型 file-extension: yml #配置中心编码 encode: utf-8 management: endpoints: web: exposure: include: '*'     bootstrap.yml service-gateway-dev.yml spring: application: name: service-gateway profiles: active: dev cloud: nacos: config: #配置中心文件类型 f i l e- ex t en sion: yml #配置 中 心 服 务 地 址 se rv e r- addr: 172.17.0.225:8848,172.17.0.225:8849,172.17.0.225:8850 #配置 中 心 编 码 encode: utf-8 server: port: 6666 spring: sleuth: sampler: probability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1 zipkin: base-url: http://172.17.0.225:9411/ # 指定了 Zipkin 服务器的地址 application: name: service-gateway cloud: nacos: discovery: server-addr: 172.17.0.225:8848,172.17.0.225:8849,172.17.0.225:8850 gateway: discovery: #为true表明Gateway开启服务注册和发现的功能 locator: #是否与服务发现组件进行结合,通过 serviceId 转发到具体的服务实例。默认为false,设为true便开 启通过服务中心的自动根据 serviceId 创建路由的功能。 #路由访问方式:http://Gateway_HOST:Gateway_PORT/serviceId/**,其中微服务应用名默认大写 访问。 enabled: false #默认false;serviceId为大写 lowerCaseServiceId: false routes: #配置路由 - id: service-elasticsearch uri: lb://service-elasticsearch predicates: # 匹配路径转发 - Path=/v1/docs/**,/v1/indices/** - id: service-analysis uri: lb://service-analysis predicates: # 匹配路径转发 - Path=/v1/analysis/**     4、Postman访问 参数 返回 http://172.17.0.225:6666/v1/docs/mquery 或者 http://127.0. 0.1:8888/v1/docs/mquery { "pag eNumber": 1, "pageSize": 10, "indexName": "product_list_info", "highlight": "productname", "map": { "productname": "华为全面屏" } } { "code": "200", "desc": "操作成功!", "data": [ { "score": 8.343819, "id": "5818822", "type": "_doc", "nestedIdentity": null, "version": -1, "seqNo": -2, "primaryTerm": 0, "fields": {}, "highlightFields": { "productname": { "name": "productname", "fragments": [ { "fragment": true } ], "fragment": true } }, "sortValues": [], "matchedQueries": [], "explanation": null, "shard": null, "index": "product_list_info", "clusterAlias": null, "sourceAsMap": { "twolevel": "功能箱包",     【笔记本 】 [全面屏手机] "storename": "鹏若拼购店", "evalcount": 415097, "threelevel": "旅行配件", "storetype": "店铺发货", "@timestamp": "2020-03-21T19:49:03.148Z", "purchaseindex": "0", "onelevel": "箱包皮具", "price": 40.6, "fourlevel": null, " @ v e r s io n " : " 1 " , " p ro d u c t na m e " : " <span style= color:red;font-weight:bold;font size:15px ; > 华 为 < / s p a n > w a t c h 2 保 护 壳 < sp an s t y l e = c o l o r : r e d ; f o n t - w e i g ht:bold;font size:15px ; > 华 为 < / s p a n > W a t c hG T 手 表 保 护 壳 < s p a n s t y l e = c o l o r : r e d ; f o n t  weight:b o l d ;f o n t - s iz e: 1 5 px ; > 华 为 < / s p a n > w a t c h 2p r o 黑 色 适 用 : < s p a n s ty le= color:re d ; fo n t -w e i g ht :b o l d ; f on t- s i z e : 1 5 p x ; > 华 为 < / s pa n >w at c h 2 P r o " , "id": 5818822, "sku": "54011029913", "updatetime": "2020-03-18T05:01:57.000Z" }, "innerHits": null, "sourceRef": { "fragment": true }, "sourceAsString": "{\"storetype\":\"店铺发货 \",\"@version\":\"1\",\"@timestamp\":\"2020-03- 21T19:49:03.148Z\",\"price\":40.6,\"sku\":\"54011029913\",\"onelevel\":\"箱包皮具 \",\"id\":5818822,\"evalcount\":415097,\"purchaseindex\":\"0\",\"updatetime\":\" 2020-03-18T05:01:57.000Z\",\"fourlevel\":null,\"twolevel\":\"功能箱包 \",\"threelevel\":\"旅行配件\",\"storename\":\"鹏若拼购店\",\"productname\":\"\\n华 为watch2保护壳华为WatchGT手表保护壳华为watch2pro黑色适用:华为watch2Pro\"}", "rawSortValues": [], "fragment": false } ], "count": 70854 }     高亮显示:在线html编辑器 HTML代码如下: 4 电商平台结构化搜索与排序 4.1 结构化搜索介绍 结构化搜索( Structured search) 是指具有内在结构数据的过程。 4.2 电商下结构化搜索 https://c.runoob.com/front-end/61 <span style= color:red;font-weight:bold;font-size:15px;>华为</span>(HUAWEI) <span style= color:red;font-weight:bold;font-size:15px;>华为</span>mate20pro手机 <span style= color:red;font-weight:bold;font-size:15px;>全面屏</span>亮黑色全网通 8GB+128GB     查询二级类目 价格在【 2000-3000】并且是【京东物流】并且评论数【从大到小进行排序】的商品 4.2.1 传统实现方式 实现查询手机的价格在【 2000-3000】并且是【京东物流】并且评论数【从大到小进行排序】的商品     4.2.2 终搜平台实现方式 1)DSL语法分析 DSL: ES支持一种JSON格式的查询,叫做DSL,domain specifific language 结构化查询(Query DSL): query的时候,会先比较查询条件,然后计算分值,最后返回文档结果 结构化过滤( Filter DSL): 过滤器,对查询结果进行缓存,不会计算相关度,避免计算分值,执行速度非常快 1、结构化查询,需要传递 query 参数 比如match_all、match、fifilter、bool SELECT * FROM product_list WHERE price BETWEEN 2000 AND 3000 AND store_type = '自营' AND two_l evel_category = '手机' ORDER BY eval_count DESC GET /_search { "query": 各种查询参数 }     2、结构化过滤( Filter DSL) term 过滤 term 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本 数据类型),相当于sql age=26 terms 过滤 terms 允许指定多个 匹配条件。如果某个字段指定了多个值,那么文档需要一起去做匹配。 相当于sql: a ge in range 过滤 range 过滤允许我们按照指定范围查找一批数据: 相等于sql between bool 过滤 用来合并多个过滤条件查询结果的布尔逻辑: must:多个查询条件的完全匹配,相当于 and。 must_not: 多个查询条件的相反匹配,相当于 not; should:至少有一个查询条件匹配,相当于 or; 相当于sql and 和or 不常用 exists 和 missing 过滤 用于查找文档是否包含指定字段或没有某个字段,类似于 SQL 语句中的 IS_NULL 条件 {"term": {"age": 26}} {"terms" : {"age": [26, 27, 28]}} { "range": { "price": { "gte": 2000, "lte": 3000 } } } gt : 大于 lt : 小于 gte : 大于等于 lte :小于等于     电商产品搜索DSL实现 注意: 被查询的字段类型是必须是keyword,这样字段在索引时不会进行分词。如果类型为text,字段值 在索引时会分词,这样反而查不到结果了。 如果映射不满足条件怎么办? 重建索引即可 实现查询价格在 【 2000-3000】并且是【京东物流】并且评论数【从大到小进行排序】的商品 fifilter也常和r ange范围查询一起结合使用,range范围可供组合的选项 GET product_list_info/_search { "query": { "bool": { "must": [ { "term": { "storetype": "自营" } }, { "term": { "twolevel": "手机" } } ], "filter": { "range": { "price": { "gte": 2000, "lte": 3000 } } } } }, "sort": [ { "evalcount": { "order": "desc" } } ] }     2)终搜OpenAPI 接口 控制器代码 package com.itheima.service; import com.itheima.commons.pojo.CommonEntity; import org.elasticsearch.action.DocWriteResponse; import org.el a s t i c s e a r c h . a ct io n . s ea r c h .S e archResponse; import org.el a s t i c s e a r c h . re st .R e s t St a t u s ; import org.elasticsearch.search.SearchHit; import jav a.util.List; import j ava.util.Map; /** * @Class: ElasticsearchDocumentService * @Package com.itheima.service * @Description: 文档操作接口 * @Company: http://www.itheima.com/ */ public interface ElasticsearchDocumentService { //结构化查询 public SearchResponse termQuery(CommonEntity commonEntity) throws Exception; } /* * @Description: 结构化搜索(查询手机在2000-3000元之间、京东物流发货,按照评价进行排 序) * @Method: termquery * @Param: [commonEntity] * @Update: * @since: 1.0.0 * @Return: com.itheima.commons.result.ResponseData * */ @GetMapping(value = "/tquery") public ResponseData termQuery(@RequestBody CommonEntity commonEntity) { // 构造返回数据 ResponseData rData = new ResponseData(); //批量查询返回结果 SearchResponse result = null; try { //通过高阶API调用批量新增操作方法 result = elasticsearchDocumentService.termQuery(commonEntity); //查询数量除以每页数量 等于合计分页数量 long aSize = result.getHits().getTotalHits().value; logger.info("总数据量:" + aSize + "条"); int cSize = result.getHits().getHits().length; logger.info("当前获取数据:" + cSize + "条"); //通过类型推断自动装箱(多个参数取交集)     实现类 rData.setResultEnum(result.getHits().getHits(), ResultEnum.success, Integer.valueOf(String.valueOf(aSize))); //日志记录 logger.info(TipsEnum.batch_get_doc_success.getMessage()); } catch (Exception e) { //打印到控制台 e.printStackTrace(); //日志记录 logger.error(TipsEnum.batch_get_doc_fail.getMessage()); / / 构 建 错 误 返 回 信 息 r D at a. s et Re s ul tEnum(ResultEnum.error); } re turn rData; } /* * @Description:结构化搜索 * @Method: termQuery * @Param: [commonEntity] * @Update: * @since: 1.0.0 * @Return: org.elasticsearch.action.search.SearchResponse * */ public SearchResponse termQuery(CommonEntity commonEntity) throws Exception { //构建查询响应 SearchResponse response = null; //构建查询请求用来完成和搜索文档,聚合,建议等相关的任何操作同时也提供了各种方式来完成 对查询结果的高亮操作。 SearchRequest searchRequest = new SearchRequest(commonEntity.getIndexName()); //构建DSL请求体trackTotalHits如果不设置true,查询数据最大值还是10000 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true); //将前端的dsl查询转化为XContentParser XContentParser parser = SearchTools.getXContentParser(commonEntity); //将parser解析成功查询API searchSourceBuilder.parseXContent(parser); //高亮设置 searchSourceBuilder.highlighter(SearchTools.getHighlightBuilder(commonEntity.get Highlight())); //前端页码 int pageNumber = commonEntity.getPageNumber(); //前端每页数量 int pageSize = commonEntity.getPageSize(); //计算查询的下标 int dest = (pageNumber - 1) * pageSize; searchSourceBuilder.from(dest); //每页数量 searchSourceBuilder.size(pageSize);     访问地址 1、公共参数抽取 pageNumber:表示前端页码 pageSize:表示每页显示大小 indexName:要查询的索引名称,不允许为空 sortField:排序的列,可以为空 sortOrder:取值范围ASC DESC ,不区分大小写,可以为空默认为DESC, //排序 sort(commonEntity, searchSourceBuilder); //查询条件对象放入请求对象中 searchRequest.source(searchSourceBuilder); //方法执行开始时间 long startTime = System.currentTimeMillis(); System.out.println("开始Elasticsearch查询..."); //执行 远 程 查 询 respo n s e = client.search(searchRequest, RequestOptions.DEFAULT); // 计 算 远 程 查 询 耗 时 Sy st em . ou t .p ri ntln("结束Elasticsearch查询总耗时:" + (System. c u rr en tT imeMillis() - startTime) + "毫秒"); / / 处 理 高 亮 SearchTools.setHighResultForCleintUI(response, commonEntity.getHighlight()); return response; } http://172.12.0.225:6666/v1/docs/tquery 或者 http://localhost:8888/v1/docs/tquery           highlight:高亮列,可以为空 2、动态参数解析 排序方式一 { "pageNumber": 1, "pageSize": 1, "indexName": "product_list_info", "sortField": "evalcount", "sortOrder": "", "highlight": "productname", "map": { "query": { "bool": {pageNumber:页码 pageSize:每页显示条数 indexName:不可以为空,查询的索引名称 sortField:排序列,可以为空 sortOrder:可以为空,默认DESC,排序规则【DESC/ASC】 highlight:高亮字段(注意:平台只接受被查询的字段名称) map:里面的参数为动态DSL参数;可以随意增加(需符合ES规范)系统可自动解析 排序方式二 "must": [ { "term": { "storetype": "自营" } }, { "term": { "twolevel": "手机" } } ] , "f ilter": { " r a ng e " : { " p ri ce ": { "gte": 2000, "lte": 3000 } } } } } } } { "pageNumber": 1, "pageSize": 1, "indexName": "product_list_info", "sortField": "", "sortOrder": "", "highlight": "productname", "map": { "query": { "bool": { "must": [ { "term": { "storetype": "自营" }     返回 }, { "term": { "twolevel": "手机" } } ], "filter": { "range": { " p r ic e " : { "g t e " : 2000, "lte": 3000 } } } } }, "sort": [ { "evalcount": { "order": "desc" } } ] } } { "code": "200", "desc": "操作成功!", "data": [ { "score": "NaN", "id": "197028", "type": "_doc", "nestedIdentity": null, "version": -1, "seqNo": -2, "primaryTerm": 0, "fields": {}, "highlightFields": { "productname": { "name": "productname", "fragments": [ { "fragment": true } ], "fragment": true } }, "sortValues": [ 1067122     ], "matchedQueries": [], "explanation": null, "shard": null, "index": "product_list_info", "clusterAlias": null, "sourceAsMap": { "twolevel": "手机", "storename": "荣耀京东自营旗舰店", " ev a l co u nt " : 10 67 12 2 , "t h re e le v el " : "手 机 " , " st o re t y p e " : " 自 营 " , "@ t im e s ta m p " : " 2 02 0 -03-21T20:01:41.981Z", " pu rc h a se i n de x" : " 0" , "o ne le v e l " : "手 机 通 讯 " , "price": 2699.0, "fourlevel": null, "@version": "1", "productname": "荣耀20李现同款4800万超广角AI四摄3200W美颜自拍麒麟 Kirin980全网通版8GB+256GB蓝水翡翠全面屏<span style= color:red;font-weight:bold;font size:15px;>手机</span>", "id": 197028, "sku": "100006268939", "updatetime": "2020-03-17T17:00:07.000Z" }, "innerHits": null, "sourceRef": { "fragment": true }, "sourceAsString": "{\"storetype\":\"自营 \",\"@version\":\"1\",\"@timestamp\":\"2020-03- 21T20:01:41.981Z\",\"price\":2699.0,\"sku\":\"100006268939\",\"onelevel\":\"手机 通讯 \",\"id\":197028,\"evalcount\":1067122,\"purchaseindex\":\"0\",\"updatetime\":\" 2020-03-17T17:00:07.000Z\",\"fourlevel\":null,\"twolevel\":\"手机 \",\"threelevel\":\"手机\",\"storename\":\"荣耀京东自营旗舰店 \",\"productname\":\"\\n荣耀20李现同款4800万超广角AI四摄3200W美颜自拍麒麟Kirin980全网通 版8GB+256GB蓝水翡翠全面屏手机\"}", "rawSortValues": [], "fragment": false } ], "count": 29 }      

标签:product,jdbc,WM,sql,查询,port,mysql,stage1,logstash
From: https://www.cnblogs.com/shan13936/p/17403385.html

相关文章

  • Python数据库篇:sqlite3、mysql、sqlalchemy
    一:sqlite3importsqlite3conn=sqlite3.connect("test.db")cursor=conn.cursor()cursor.execute("createtableuser(idvarchar(20)primarykey,namevarchar(20))")cursor.execute("insertintouser(id,name)values(\'1\�......
  • 【MySQL--09】表的内连和外连
    【MySQL--09】表的内连和外连表的连接分为内连接和外连接1.1内连接内连接实际上就是利用where子句对两种表形成的笛卡尔积进行筛选,我们之前所用的查询都是内连接,也是在开发过程中使用的最多的连接查询。select字段from表1innerjoin表2on连接条件and其他条件;备注:前......
  • MySQL开机自启
    linux上设置mysql开机自启1、普通启动,进入mysql安装路径:/usr/local/mysqlservicemysqlstart2、这个时候我们只是单纯的启动了mysql,并没有做到开机启动我们设置开机启动需要将mysql.server文件复制到/etc/rc.d/init.d/目录下mysql文件我们的mysql.server文件一般都在安......
  • MySQL高级——Explain信息中rows字段解释
    一、Explain信息中rows字段解释根据表统计信息及索引选用情况,大致估算出找到所需要的记录所需要读取的行数(即每张表有多少行被优化器查询),所需读取的行数越少越好。二、Explain信息中rows字段解释的示例1、没建立索引之前,rows字段表示需要从t2表读取640行数据(即t2表有640行被优化器......
  • MySQL配置免密登录及密码修改
    内容要点一、问题描述二、解决方案一、问题描述1、mysql忘记密码无法登录。报错:#mysql-uroot-pEnterpassword:ERROR1045(28000):Accessdeniedforuser'root'@'localhost'(usingpassword:YES)2、配置免密登录后修改密码失败UPDATEuserSETpassword=PASSWORD('r......
  • WM_大屏实时计算深度剖析 flink写es kafka cannal配置 暂时没用
    第1章大屏实时计算深度剖析学习目标目标1:了解实时计算的应用场景目标2:实时流计算的快速入门(Flink的入门使用)目标3:Flink接入技术体系的剖析(hdfs,jdbc,kafka,socket)目标4:Flink数据处理引擎的实战(采用双十一大屏,热销数据统计,区域分类统计,cep复杂事件的处理)目标5:实时......
  • 将CSV导入到MySQL数据库
    参考:https://blog.csdn.net/fwdwqdwq/article/details/126081152.使用一下命令查看是否允许从外部路径导入文件mysql>showvariableslike"%secure%";+--------------------------+-------+|Variable_name|Value|+--------------------------+-------+|r......
  • mysql ssl
    服务器提示:Causedby:javax.net.ssl.SSLHandshakeException:Remotehostclosedconnectionduringhandshake,atsun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002)~[na:1.8.0_161],atsun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSoc......
  • mysql终止慢查询进程
    要终止执行慢查询的MySQL进程,你可以使用`KILL`语句。以下是在MySQL中使用`KILL`语句终止慢查询的一般步骤:1.首先,使用以下命令查找正在执行的慢查询的进程ID(也称为线程ID):SHOWFULLPROCESSLIST;这将显示当前正在执行的所有MySQL进程的列表,包括进程ID、执行时间和查询语句。2......
  • NetBackup 10.2 新功能介绍:PostgreSQL 和 MySQL 自动化恢复达成
    VeritasNetBackup10.2(Unix,Linux,Windows)下载-一流的企业备份和恢复原文来自:VERITAS中文社区2023-04-27在执行恢复任务时,手动提取、更新数据库和实例并将其附加到PostgreSQL和MySQL是常规操作。而在最新的NetBackup10.2版本中,执行恢复已不再需要上述手动流程......