当前位置: 首页 > news >正文

ES8的Java API client 8.0 简单示例操作 Elasticsearch

1.加入依赖

      <dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.12.2</version></dependency>

2.配置类

@Slf4j
@Configuration
public class ElasticSearchConfig {@Value("${elasticsearch.hosts}")private String hosts;@Value("${elasticsearch.port}")private int port;@Value("${elasticsearch.username}")private String username;@Value("${elasticsearch.password}")private String password;@Value("${elasticsearch.apikey:''}")private String apikey;/*** 单节点没密码连接** @return*/@Beanpublic ElasticsearchClient elasticsearchClient() {String[] servers = hosts.split(",");int len = servers.length;if (0 == len) {log.error("ElasticsearchClient 配置错误!");}ElasticsearchTransport transport = null;// 不是集群时if (1 == len) {// 无账号、密码if (StringUtils.isEmpty(username) && StringUtils.isEmpty(password)) {RestClient client = RestClient.builder(new HttpHost(servers[0], port, "http")).setHttpClientConfigCallback(httpClientBuilder->httpClientBuilder.setDefaultHeaders(Collections.singletonList(new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()))).addInterceptorLast((HttpResponseInterceptor) (response, context)-> response.addHeader("X-Elastic-Product", "Elasticsearch"))).build();transport = new RestClientTransport(client, new JacksonJsonpMapper());} else {// 账号密码的配置final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));// 自签证书的设置,并且还包含了账号密码RestClientBuilder.HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider).addInterceptorLast((HttpResponseInterceptor)(response, context) ->response.addHeader("X-Elastic-Product", "Elasticsearch"));RestClient client = RestClient.builder(new HttpHost(servers[0], port, "http")).setHttpClientConfigCallback(callback).build();transport = new RestClientTransport(client, new JacksonJsonpMapper());}} else {// 集群时无账号、密码if (StringUtils.isEmpty(username) && StringUtils.isEmpty(password)) {transport = getElasticsearchTransport(toHttpHost());} else {transport = getElasticsearchTransport(username, password, toHttpHost());}}return new ElasticsearchClient(transport);}private HttpHost[] toHttpHost() {if (hosts.split(",").length == 0) {throw new RuntimeException("invalid elasticsearch configuration");}String[] hostArray = hosts.split(",");HttpHost[] httpHosts = new HttpHost[hostArray.length];HttpHost httpHost;for (int i = 0; i < hostArray.length; i++) {String[] strings = hostArray[i].split(":");httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "http");httpHosts[i] = httpHost;}return httpHosts;}private static ElasticsearchTransport getElasticsearchTransport(String username, String password, HttpHost... hosts) {// 账号密码的配置final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));// 自签证书的设置,并且还包含了账号密码RestClientBuilder.HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder.setSSLContext(buildSSLContext()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setDefaultCredentialsProvider(credentialsProvider).setDefaultHeaders(Stream.of(new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())).collect(toList())).addInterceptorLast((HttpResponseInterceptor)(response, context) ->response.addHeader("X-Elastic-Product", "Elasticsearch")).addInterceptorLast((HttpResponseInterceptor) (response, context)-> response.addHeader("X-Elastic-Product", "Elasticsearch"));// 用builder创建RestClient对象RestClient client = RestClient.builder(hosts).setHttpClientConfigCallback(callback).build();return new RestClientTransport(client, new JacksonJsonpMapper());}private static ElasticsearchTransport getElasticsearchTransport(HttpHost... hosts) {// 用builder创建RestClient对象RestClient client = RestClient.builder(hosts).build();return new RestClientTransport(client, new JacksonJsonpMapper());}private static SSLContext buildSSLContext() {ClassPathResource resource = new ClassPathResource("es01.crt");SSLContext sslContext = null;try {CertificateFactory factory = CertificateFactory.getInstance("X.509");Certificate trustedCa;try (InputStream is = resource.getInputStream()) {trustedCa = factory.generateCertificate(is);}KeyStore trustStore = KeyStore.getInstance("pkcs12");trustStore.load(null, null);trustStore.setCertificateEntry("ca", trustedCa);SSLContextBuilder sslContextBuilder = SSLContexts.custom().loadTrustMaterial(trustStore, null);sslContext = sslContextBuilder.build();} catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException |KeyManagementException e) {log.error("ES连接认证失败", e);}return sslContext;}
}

3.相关api

前提:

注入ElasticsearchClient

@Autowired
private ElasticsearchClient client;

3.1 创建索引

 public void createIndex() throws IOException {ElasticsearchIndicesClient indices = client.indices();//是否存在//1.lambdaboolean isExit = indices.exists(req -> req.index("ttt")).value();//2.builder,ofExistsRequest existsRequestOf = ExistsRequest.of(req -> req.index("ttt"));ExistsRequest existsRequest = new ExistsRequest.Builder().index("ttt").build();boolean builderExist = indices.exists(existsRequest).value();if (isExit){log.info("已经存在ttt");}else {//1.lambdaboolean isSuccess = indices.create(req -> req.index("ttt")).acknowledged();//2.builder,ofCreateIndexRequest createIndexRequestOf = CreateIndexRequest.of(req -> req.index("ttt"));CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder().index("ttt").build();boolean buildIsSuccess = indices.create(createIndexRequest).acknowledged();if (isSuccess){log.info("创建成功");}else {log.info("创建失败");}}}

3.2 删除索引

public void deleteIndex() throws IOException {//1.lambdaboolean isSuccess = client.indices().delete(req -> req.index("ttt")).acknowledged();//2.builder,ofDeleteIndexRequest deleteRequestOf = DeleteIndexRequest.of(req -> req.index("ttt"));DeleteIndexRequest deleteRequest = new DeleteIndexRequest.Builder().index("ttt").build();boolean buildDeleteRequest = client.indices().delete(deleteRequest).acknowledged();}

3.3查询索引

 public void queryIndex() throws IOException {//1.lambda//查询单个Map<String, IndexState> tttIndex = client.indices().get(req -> req.index("ttt")).result();//查询索引Set<String> all = client.indices().get(req -> req.index("*")).result().keySet();//2.builderGetIndexRequest getIndexRequestOf = GetIndexRequest.of(req -> req.index("ttt"));GetIndexRequest getIndexRequest = new GetIndexRequest.Builder().index("ttt").build();Map<String, IndexState> result = client.indices().get(getIndexRequest).result();}

3.4 插入文档

 public void addDoc() throws IOException {Goods goods = new Goods("3212334","华为mate60", 9999.0);//1.lambdaclient.index(i->i.index("goods").id(goods.getSku()).document(goods));//2.builder-ofIndexRequest<Goods> addIndexRequestOf = IndexRequest.of(t -> t.id(goods.getSku()).document(goods).index("goods"));IndexRequest<Goods> addIndexRequest = new IndexRequest<>.Builder().index("goods").id(goods.getSku()).document(goods).build();IndexResponse index = client.index(addIndexRequest);}

3.5 批量插入文档

public void addBatchDoc() throws IOException {List<Goods> goodsList = List.of(new Goods("1","手机",999.0));BulkRequest.Builder br = new BulkRequest.Builder();for (Goods goods : goodsList) {br.operations(op->op.index(idx->idx.index("goods").id(goods.getSku()).document(goods)));}BulkResponse result = client.bulk(br.build());// Log errors, if anyif (result.errors()) {log.error("Bulk had errors");for (BulkResponseItem item: result.items()) {if (item.error() != null) {log.error(item.error().reason());}}}}

3.6查询文档

public void queryDoc() throws IOException {//1.lambdaGetResponse<Goods> response = client.get(g ->  g.index("goods").id("00000"), Goods.class);//2.builder,ofGetRequest request = GetRequest.of(g -> g.index("goods").id("00000"));GetRequest ofRequest = new GetRequest.Builder().index("goods").id("00000").build();GetResponse<Goods> response1 = client.get(request, Goods.class);if (response.found()){Goods source = response.source();System.out.println(source);}}

3.7修改文档

 public void updateDoc() throws IOException {//全量Goods goods = new Goods("1","2",3.0);UpdateResponse<Goods> update = client.update(u -> u.doc(goods).id(goods.getSku()), Goods.class);//ofUpdateRequest<Object, Object> of = UpdateRequest.of(u -> u.id(goods.getSku()).doc(goods));UpdateResponse<Object> update1 = client.update(of, Goods.class);}

3.8删除文档

   */public void deleteDoc() throws IOException {DeleteResponse goods = client.delete(d -> d.index("goods").id("0000"));//ofDeleteRequest deleteRequest = DeleteRequest.of(d -> d.index("goods").id("0000"));client.delete(deleteRequest);}

3.9 DSL 匹配查询

public void query() throws IOException {String text = "华为mate60";SearchResponse<Goods> response = client.search(s -> s.index("goods").query(q -> q.match(m -> m.field("name").query(text))), Goods.class);//ofSearchRequest request = SearchRequest.of(s -> s.index("goods").query(q -> q.match(m ->m.field("").field(""))));SearchResponse<Goods> search = client.search(request, Goods.class);//结果//总数TotalHits total = response.hits().total();assert total != null;boolean isExactResult = total.relation() == TotalHitsRelation.Eq;if (isExactResult) {log.info("找到 " + total.value() + " 个结果");} else {log.info("找到超过 " + total.value() + " 个结果");}List<Hit<Goods>> hits = response.hits().hits();for (Hit<Goods> hit : hits) {Goods goods = hit.source();System.out.println(goods);}}

3.10 多精确terms

public void terms(){List<FieldValue> v = new ArrayList<>();FieldValue tag2 = FieldValue.of("tag2");FieldValue tag1 = FieldValue.of("tag1");v.add(tag1);v.add(tag2);TermsQuery tags = TermsQuery.of(t -> t.field("tags").terms(tm -> tm.value(v)));SearchRequest of = SearchRequest.of(s -> s.index("goods").query(q -> q.bool(b -> b.must(m -> m.terms(tags)).should(sh -> sh.match(ma -> ma.field("").query(""))))).from(0).size(10));}

3.11 布尔查询

@Slf4j
@Service
public class EsTest {@Autowiredprivate ElasticsearchClient client;/*** bool*/public void boolQuery() throws IOException {Map<String, HighlightField> map = new HashMap<>();map.put("title", HighlightField.of(hf -> hf.preTags("<em>").postTags("<em/>")));map.put("description", HighlightField.of(hf -> hf.preTags("<em>").postTags("<em/>").numberOfFragments(4).fragmentSize(50)));//numberOfFragments(4),表示将字段分割为最多4个片段,并设置 fragmentSize(50),表示每个片段的大小为50个字符。Highlight highlight = Highlight.of(h -> h.type(HighlighterType.Unified).fields(map).fragmentSize(50)//设置默认的高亮片段大小为50个字符,如果字段没有单独设置,则使用此默认值。.numberOfFragments(5)//设置每个字段的最大高亮片段数为5个。);String text = "华为mate60";SearchResponse<Goods> search = client.search(s -> s.index("goods").query(q -> q.bool(b -> b.must(m -> m.term(t -> t.field("品牌").value("华为"))).should(sd -> sd.match(mh -> mh.field("name").query("mate60"))))).from(0).size(10).highlight(highlight), Goods.class);//ofSearchRequest of = SearchRequest.of(s -> s.index("goods").query(q -> q.bool(b -> b.must(m -> m.term(t -> t.field("品牌").value("华为"))).should(sh -> sh.match(ma -> ma.field("").query(""))))).from(0).size(10).highlight(highlight));SearchResponse<Goods> response = client.search(of, Goods.class);List<Hit<Goods>> hits = response.hits().hits();for (Hit<Goods> hit : hits) {Goods goods = hit.source();if (goods == null){continue;}Map<String, List<String>> highlightList = hit.highlight();highlightList.forEach((key, Value)->{if (Objects.equals(key,goods.getName())){//存入}else {//无高亮}});System.out.println(goods);}}}

3.12构建排序

/*** 构建排序*/private List<SortOptions> buildSort(SearchDTO dto) {if (dto.getTimeSort() != null){SortOptions sortOptions ;if (dto.getTimeSort() == 0){sortOptions = SortOptions.of(s -> s.field(FieldSort.of(f -> f.field(SearchConstants.TIMESTAMP).order(SortOrder.Asc))));}else {sortOptions = SortOptions.of(s -> s.field(FieldSort.of(f -> f.field(SearchConstants.TIMESTAMP).order(SortOrder.Desc))));}return List.of(sortOptions);}else {return Collections.emptyList();}}

...........

相关文章:

ES8的Java API client 8.0 简单示例操作 Elasticsearch

1.加入依赖 <dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.12.2</version></dependency>2.配置类 Slf4j Configuration public class ElasticSearchConfig {Valu…...

多线程CompletableFuture

最近发现同事整理了一个不错的关于CompletableFuture的文档&#xff0c;在这里记录一下&#xff0c;方便以后工作备用 CompletableFuture future CompletableFuture.supplyAsync(() -> {return "开新线程异步执行"; })result future.get(); // 线程阻塞等待结果…...

AR传送门+特定区域显示内容+放大镜 效果着色器使用

AR传送门特定区域显示内容放大镜 效果 关键词&#xff1a;Portal Mask 1、教程链接&#xff1a; AR 传送门教程 Unity - Portal Mask Implementation - Part 4_哔哩哔哩_bilibili 应用案例效果&#xff1a; 2、案例下载地址&#xff1a;使用unity 2021.3.33f1 obi 工具…...

设置Hadoop守护进程的JVM参数

一般情况下我们不去动守护进程的JVM&#xff0c;这里的守护进程说的是NameNode、DataNode等Hadoop服务自己本身的进程。但是有一些特殊情况下需要限制&#xff0c;比如工作中虽然集群中资源队列会有10%左右的预留空余&#xff0c;不过这是整个集群队列的限制&#xff0c;对于Da…...

可视化大屏

可视化大屏 是一种利用计算机图形学技术&#xff0c;将复杂的数据和信息转换为直观的可视化图形&#xff0c;以呈现数据信息的工具。它不仅在电影中常见&#xff0c;而且已经实实在在地被应用在商业、金融、制造等各个行业的业务场景中&#xff0c;成为大数据分析和展示的重要工…...

pytest框架

pytest测试框架 单元测试框架定义&#xff1a;针对软件开发最小的单元&#xff08;函数&#xff0c;方法&#xff09;进行正确性位置测试 单元测试框架&#xff1a;java&#xff08;junit&#xff0c;testing&#xff09;python&#xff08;unittest&#xff0c;pytest&#…...

基于大数据的亚健康人群数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…...

黄金短线交易策略:波动中的高效盈利之法

今日&#xff0c;亚市盘初&#xff0c;现货黄金就高位震荡。在昨日金价再度冲高&#xff0c;一度刷新历史高点至2685.49美元&#xff0c;收报2672.25美元。其中主要原因是美国公布了最新的核心PCE&#xff08;个人消费支出&#xff09;物价指数和初请失业金人数等经济数据&…...

西陆家政系统V1.0.1

微信小程序开发的西陆家政服务管理系统小程序 V1.0.1bug修复优化 1.修复首页轮播不能自动轮播问题;2.修复订单详情价格显示问题;3.修复在开放城市模式下,其他城市可以下单问题;4.修复个人二维码跳转小程序路径异常问题;5.修复小程序编辑我的地址选择定位后不刷新问题&#xf…...

时间安全精细化管理平台/iapp/mobile/facereg/facereg.html接口存在未授权访问漏洞

漏洞描述 登录--时间&安全精细化管理平台/iapp/mobile/facereg/facereg.html接口存在未授权访问漏洞&#xff0c;黑客可以未授权等级员工信息对平台造成影响 FOFA&#xff1a; body"登录--时间&amp;安全精细化管理平台" 漏洞复现 IP/iapp/mobile/facereg…...

自动化测试实例:Web登录功能性测试(无验证码)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是自动化测试 把人为驱动的测试行为转化为机器执行的一种过程称为自动化测试。(来自百度百科)本质上来说&#xff0c;自动化测试对比起手工测试除了需要…...

【算法篇】二叉树类(3)(笔记)

目录 一、Leetcode 题目 1. 二叉树的最近公共祖先 2. 二叉搜索树的最近公共祖先 &#xff08;1&#xff09;递归法 &#xff08;2&#xff09;迭代法 3. 二叉搜索树中的插入操作 &#xff08;1&#xff09;递归法 &#xff08;2&#xff09;迭代法 4. 删除二叉搜索树中…...

基于php的律所管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…...

MySQL 之索引详解

想象一下&#xff0c;你正在图书馆寻找一本关于 MySQL 索引的书。图书馆里有成千上万本书&#xff0c;但没有目录。你只能一排一排、一本一本地找&#xff0c;直到找到你想要的书。这将会花费大量的时间&#xff01;数据库索引就像图书馆的目录一样&#xff0c;可以帮助数据库系…...

C#测试调用FreeSpire.PDFViewer浏览PDF文件

Free Spire.PDFViewer是商业版Spire.PDFViewer的社区版本&#xff0c;支持以控件形式打开并查看PDf文件&#xff0c;但由于是免费版本&#xff0c;存在使用限制&#xff0c;打开的PDF文档只显示前10页内容。如果日常操作的pdf文件都不超过10页&#xff0c;可以考虑使用Free Spi…...

又一挣钱副业:AI生成影视解说,半个月涨粉变现3.5W+!

这两年大家都在感叹生活不易&#xff0c;然而我想说的是&#xff0c;机会还是有的&#xff0c;但问题不在于有没有&#xff0c;而在于你是否能够认准机会&#xff0c;然后抓住它。 接触过很多咨询项目的人&#xff0c;发现很多人依旧停留在传统思维中&#xff0c;认为副业就是…...

R语言 基础 笔记 3

起因, 目的: 思考一个问题: AI 这么强,AI 什么都知道,为什么还要学习这些基础的东西, 为什么还要写这些笔记? 我觉得,大体过一遍,还是有好处的。 有个大致印象,下次查的时候,也方便一些。 几个函数 cbind() 按照列,拼接数据, 会改变某些列的数据类型。data() 查看…...

【MySQL】常见的SQL优化方式(一)

目录 1、插入数据 &#xff08;1&#xff09;批量插入 &#xff08;2&#xff09;手动提交事务 &#xff08;3&#xff09;主键顺序插入 2、主键优化 &#xff08;1&#xff09;页分裂 &#xff08;2&#xff09;页合并 3、order by 优化 &#xff08;1&#xff09;排…...

【重点】使用axios.request.put上传文件,报错分析

使用axios的put方法上传文件时&#xff0c;如果遇到错误&#xff0c;可能的原因有以下几点&#xff1a; 跨域问题&#xff1a;如果请求的URL与当前页面的域名不同&#xff0c;可能会触发跨域问题。解决方法是在服务器端设置允许跨域请求&#xff0c;如设置CORS&#xff08;跨域…...

最新最全的阿里大模型面试真题!看到就是赚到

前言 随着人工智能技术的飞速发展&#xff0c;计算机视觉&#xff08;CV&#xff09;、自然语言处理&#xff08;NLP&#xff09;、搜索、推荐、广告推送和风险控制等领域的岗位越来越受到追捧&#xff0c;掌握大型模型技术已成为这些岗位的必备技能。然而&#xff0c;目前公开…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究

摘要&#xff1a;在消费市场竞争日益激烈的当下&#xff0c;传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序&#xff0c;探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式&#xff0c;分析沉浸式体验的优势与价值…...