SpringBoot 3.2.5 + ElasticSearch 8.12.0 - SpringData 开发指南

 

目录

一、SpringData ElasticSearch

1.1、环境配置

1.2、创建实体类

1.3、ElasticSearchTemplate 的使用

1.3.1、创建索引库,设置映射

1.3.2、创建索引映射注意事项

1.3.3、简单的 CRUD

1.3.4、三种构建搜索条件的方式

1.3.5、NativeQuery 搜索实战

1.3.6、completionSuggestion 自动补全


一、SpringData ElasticSearch


1.1、环境配置

a)依赖如下:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><!--SpringBoot3 之后测试必须引入这个包--><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>2.23.4</version><scope>test</scope></dependency>

b)配置文件如下:

spring:application:name: eselasticsearch:uris: env-base:9200

1.2、创建实体类

a)简单结构如下(后续示例,围绕此结构展开):

import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType@Document(indexName = "album_info", )
data class AlbumInfoDo (/*** @Id: 表示文档中的主键,并且会在保存在 ElasticSearch 数据结构中 {"id": "", "userId": "", "title": ""}*/@Id@Field(type = FieldType.Keyword)val id: Long? = null,/*** @Field: 描述 Java 类型中的属性映射*      - name: 对应 ES 索引中的字段名. 默认和属性同名*      - type: 对应字段类型,默认是 FieldType.Auto (会根据我们数据类型自动进行定义),但是建议主动定义,避免导致错误映射*      - index: 是否创建索引. text 类型创建倒排索引,其他类型创建正排索引.  默认是 true*      - analyzer: 分词器名称.  中文我们一般都使用 ik 分词器(ik分词器有 ik_smart 和 ik_max_word)*/@Field(name = "user_id", type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word")var title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")var content: String,
)

b)复杂嵌套结构如下:

import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType@Document(indexName = "album_list")
data class AlbumListDo(@Id@Field(type = FieldType.Keyword)var id: Long,@Field(type = FieldType.Nested) // 表示一个嵌套结构var userinfo: UserInfoSimp,@Field(type = FieldType.Text, analyzer = "ik_max_word")var title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")var content: String,@Field(type = FieldType.Nested) // 表示一个嵌套结构var photos: List<AlbumPhotoSimp>,
)data class UserInfoSimp(@Field(type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word")val username: String,@Field(type = FieldType.Keyword, index = false)val avatar: String,
)data class AlbumPhotoSimp(@Field(type = FieldType.Integer, index = false)val sort: Int,@Field(type = FieldType.Keyword, index = false)val photo: String,
)

对于一个小型系统来说,一般也不会创建这种复杂程度的文档,因为会涉及到很多一致性问题, 需要通过大量的 mq 进行同步,给系统带来一定的开销. 

因此,一般会将需要进行模糊查询的字段存 Document 中(es 就擅长这个),而其他数据则可以在 Document 中以 id 的形式进行存储.   这样就既可以借助 es 高效的模糊查询能力,也能减少为保证一致性而带来的系统开销.  从 es 中查到数据后,再通过其他表的 id 从数据库中拿数据即可(这点开销,相对于从大量数据的数据库中进行 like 查询,几乎可以忽略).

1.3、ElasticSearchTemplate 的使用

1.3.1、创建索引库,设置映射

@SpringBootTest
class ElasticSearchIndexTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate@Testfun test1() {//存在索引库就删除if (elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).exists()) {elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).delete()}//创建索引库elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).create()//设置映射elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).putMapping(elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).createMapping())}}

效果如下: 

1.3.2、创建索引映射注意事项

a)在没有创建索引库和映射的情况下,也可以直接向 es 库中插入数据,如下代码:

    @Testfun test2() {val obj = AlbumListDo(id = 1,userinfo = UserInfoSimp(userId = 1,username = "cyk",avatar = "env-base:9200"),title = "今天天气真好",content = "早上起来,我要好好学习,然去公园散步~",photos = listOf(AlbumPhotoSimp(1, "www.photo.com/aaa"),AlbumPhotoSimp(2, "www.photo.com/bbb")))val result = elasticsearchTemplate.save(obj)println(result)}

即使上述代码中 AlbumListDo 中有各种注解标记,但是不会生效!!! es 会根据插入的数据,自动转化数据结构(无视你的注解).

因此,建议先创建索引库和映射,再进行数据插入!

1.3.3、简单的 CRUD

import jakarta.annotation.Resource
import org.cyk.es.model.AlbumInfoDo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate
import org.springframework.data.elasticsearch.core.document.Document
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates
import org.springframework.data.elasticsearch.core.query.UpdateQuery@SpringBootTest
class ElasticSearchCRUDTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate@Testfun testSave() {//保存单条数据val a1 = AlbumInfoDo(id = 1,userId = 10000,title = "今天天气真好",content = "学习完之后,我要出去好好玩")val result = elasticsearchTemplate.save(a1)println(result)//保存多条数据val list = listOf(AlbumInfoDo(2, 10000, "西安六号线避雷", "前俯后仰。他就一直在那前后动。他背后是我朋友,我让他不要挤了,他直接就急了,开始故意很大力的挤来挤去。"),AlbumInfoDo(3, 10000, "字节跳动快上车~", "#内推 #字节跳动内推 #互联网"),AlbumInfoDo(4, 10000, "连王思聪也变得低调老实了", "如今的王思聪,不仅交女友的质量下降,在网上也不再像以前那样随意喷这喷那。显然,资金的紧张让他低调了许多"))val resultList = elasticsearchTemplate.save(list)resultList.forEach(::println)}@Testfun testDelete() {//根据主键删除,例如删除主键 id = 1 的文档elasticsearchTemplate.delete("1", AlbumInfoDo::class.java)}@Testfun testGet() {//根据主键获取文档val result = elasticsearchTemplate.get("1", AlbumInfoDo::class.java)println(result)}@Testfun testUpdate() {//例如,修改 id = 1 的文档val id = 1val title = "今天天气不太好"val content = "天气不好,只能在家里学习了。。。"val uq = UpdateQuery.builder(id.toString()).withDocument(Document.create().append("title", title).append("content", content)).build()val result = elasticsearchTemplate.update(uq, IndexCoordinates.of("album_info")).resultprintln(result.ordinal)println(result.name)}}

1.3.4、三种构建搜索条件的方式

关于搜索条件的构建,Spring 官网上给出了三种构建方式:Elasticsearch Operations :: Spring Data Elasticsearch

a)CriteriaQuery:允许创建查询来搜索数据,而不需要了解 Elasticsearch 查询的语法或基础知识。它们允许用户通过简单地链接和组合 Criteria 对象来构建查询,Criteria 对象指定被搜索文档必须满足的条件。

Criteria criteria = new Criteria("lastname").is("Miller") .and("firstname").is("James")                           
Query query = new CriteriaQuery(criteria);

b)StringQuery:这个类接受 Elasticsearch 查询作为 JSON String。下面的代码显示了一个搜索名为“ Jack”的人的查询:

Query query = new StringQuery("{ \"match\": { \"firstname\": { \"query\": \"Jack\" } } } ");
SearchHits<Person> searchHits = operations.search(query, Person.class);

c)NativeQuery:当您有一个复杂的查询或者一个无法使用 Criteria API 表示的查询时,例如在构建查询和使用聚合时,可以使用 NativeQuery 类。

d)到底使用哪一种呢?在最新的这一版 SpringDataES 中,NativeQuery 中可以通过大量的 Lambda 来构建条件语句,并且外观上也很符合 ElasticSearch DSL,那么对于比较熟悉原生的 DSL 语句的就建议使用 NativeQuery 啦.  我本人也更倾向 NativeQuery,因此后续的案例都会使用它.

1.3.5、NativeQuery 搜索实战

import co.elastic.clients.elasticsearch._types.SortOrder
import co.elastic.clients.json.JsonData
import jakarta.annotation.Resource
import org.cyk.es.model.AlbumInfoDo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.domain.PageRequest
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate
import org.springframework.data.elasticsearch.client.elc.NativeQuery
import org.springframework.data.elasticsearch.core.query.HighlightQuery
import org.springframework.data.elasticsearch.core.query.highlight.Highlight
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField
import org.springframework.data.elasticsearch.core.query.highlight.HighlightParameters@SpringBootTest
class SearchTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate/*** 全文检索查询(match_all)*/@Testfun testMatchAllQuery() {val query = NativeQuery.builder().withQuery { q -> q.matchAll { it }}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 精确查询(match)*/@Testfun testMatchQuery() {val query = NativeQuery.builder().withQuery { q -> q.match {it.field("title").query("天气")}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 精确查询(term)*/@Testfun testTerm() {val query = NativeQuery.builder().withQuery { q -> q.term { t -> t.field("id").value("2")}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 范围搜索*/@Testfun testRangeQuery() {val query = NativeQuery.builder().withQuery { q -> q.range { r -> r.field("id").gte(JsonData.of(1)).lt(JsonData.of(4)) // 大于等于 1,小于 4}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** bool 复合搜索*/@Testfun testBoolQuery() {val query = NativeQuery.builder().withQuery { q -> q.bool { b -> b.must { m -> m.range { r -> r.field("id").gte(JsonData.of(1)).lt(JsonData.of(4)) // 大于等于 1,小于 4}}.mustNot { n -> n.match { mc -> mcmc.field("title").query("天气")}}.should { s -> s.matchAll { it }}}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 排序 + 分页*/@Testfun testSortAndPage() {//a) 方式一
//        val query = NativeQuery.builder()
//            .withQuery { q -> q
//                .matchAll { it }
//            }
//            .withPageable(
//                PageRequest.of(0, 3) //页码(从 0 开始),非偏移量
//                    .withSort(Sort.by(Sort.Order.desc("id")))
//            ).build()//b) 方式二val query = NativeQuery.builder().withQuery { q -> q.matchAll { it }}.withSort { s -> s.field { f->f.field("id").order(SortOrder.Desc) } }.withPageable(PageRequest.of(0, 3)) //页码(从 0 开始),非偏移量).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}@Testfun testHighLight() {//所有需要高亮的字段val highField = listOf(HighlightField("title"),HighlightField("content"))val query = NativeQuery.builder().withQuery { q ->q.multiMatch { ma -> ma.fields("title", "content").query("天气")}}.withHighlightQuery(HighlightQuery(Highlight(HighlightParameters.builder().withPreTags("<span style='color:red'>") //前缀标签.withPostTags("</span>") //后缀标签.withFragmentSize(10) //高亮的片段长度(多少个几个字需要高亮,一般会设置的大一些,让匹配到的字段尽量都高亮).withNumberOfFragments(1) //高亮片段的数量.build(),highField),String::class.java)).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)//hits.content 本身是没有高亮数据的,因此这里需要手动处理hits.forEach {val result = it.content//根据高亮字段名称,获取高亮数据集合val titleList = it.getHighlightField("title")val contentList = it.getHighlightField("content")if (titleList.size > 0) result.title = titleList[0]if (contentList.size > 0) result.content = contentList[0]println(result)}}}

1.3.6、completionSuggestion 自动补全

a)自动补全的字段必须是 completion 类型. 
这里自动补全的字段为 title,通过 copyTo 将其拷贝到 suggestion 字段中,实现自动补全.
import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.CompletionField
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType
import org.springframework.data.elasticsearch.core.suggest.Completion@Document(indexName = "album_doc")
data class AlbumSugDo (@Id@Field(type = FieldType.Keyword)val id: Long,@Field(name = "user_id", type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word", copyTo = ["suggestion"]) //注意,copyTo 的字段一定是 var 类型val title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")val content: String,@CompletionField(maxInputLength = 100, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")var suggestion: Completion? = null, //注意,被 copyTo 的字段一定要是 var 类型
)

Ps:被 copyTo 的字段一定要是 var 类型

b)需求:在搜索框中输入 “今天”,对其进行自动补全.

import co.elastic.clients.elasticsearch.core.search.FieldSuggester
import co.elastic.clients.elasticsearch.core.search.FieldSuggesterBuilders
import co.elastic.clients.elasticsearch.core.search.Suggester
import jakarta.annotation.Resource
import org.cyk.es.model.AlbumSugDo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate
import org.springframework.data.elasticsearch.client.elc.NativeQuery
import org.springframework.data.elasticsearch.core.suggest.response.Suggest@SpringBootTest
class SuggestTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate@Testfun init() {if(elasticsearchTemplate.indexOps(AlbumSugDo::class.java).exists()) {elasticsearchTemplate.indexOps(AlbumSugDo::class.java).delete()}elasticsearchTemplate.indexOps(AlbumSugDo::class.java).create()elasticsearchTemplate.indexOps(AlbumSugDo::class.java).putMapping(elasticsearchTemplate.indexOps(AlbumSugDo::class.java).createMapping())elasticsearchTemplate.save(listOf(AlbumSugDo(1, 10000, "今天发现西安真美", "西安真美丽啊,来到了钟楼...."),AlbumSugDo(2, 10000, "今天六号线避雷", "前俯后仰。他就一直在那前后动。他背后是我朋友,我让他不要挤了,他直接就急了,开始故意很大力的挤来挤去。"),AlbumSugDo(3, 10000, "字节跳动快上车~", "#内推 #字节跳动内推 #互联网"),AlbumSugDo(4, 10000, "连王思聪也变得低调老实了", "如今的王思聪,不仅交女友的质量下降,在网上也不再像以前那样随意喷这喷那。显然,资金的紧张让他低调了许多")))}@Testfun suggestTest() {//模拟客户端输入的需要自动补全的字段val input = "今天"val limit = 10val fieldSuggester = FieldSuggester.Builder().text(input) //用户输入.completion(FieldSuggesterBuilders.completion().field("suggestion") //对哪个字段自动补全.skipDuplicates(true) //如果有重复的词条,自动跳过.size(limit) //最多显示 limit 条数据.build()).build()val query = NativeQuery.builder().withSuggester(Suggester.of { s -> s.suggesters("sug1", fieldSuggester) }) //参数一: 自定义自动补全名.build()val hits = elasticsearchTemplate.search(query, AlbumSugDo::class.java)val suggestList = hits.suggest?.getSuggestion("sug1")?.entries?.get(0)?.options?.map(::map) ?: emptyList()println(suggestList)}private fun map(hit: Suggest.Suggestion.Entry.Option): String {return hit.text}}

上述代码中的 hits 结构如下:

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/12696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习面试问题 | 降维

本文给大家带来的百面算法工程师是深度学习降维面试总结&#xff0c;文章内总结了常见的提问问题&#xff0c;旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中&#xff0c;我们还将介绍一些常见的深度学习面试问题&#xff0c;并提供参考的回答及其理论基础&#…

【面试必看】MySQL部分

MySQL 1. 基础 1. 什么是关系型数据库&#xff1f; 一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系&#xff08;一对一、一对多、多对多&#xff09;。各种表中&#xff08;比如用户表&#xff09;&#xff0c;表中的每一行就存放着一条…

【leetcode面试经典150题】-26. 删除有序数组中的重复项

26. 删除有序数组中的重复项 1 题目介绍1 个人解题思路1.1 解题代码1.2 思路解析 2、分析官方题解2.1 快慢双指针 1 题目介绍 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新…

新手小白如何使用云平台复现论文代码——体验yolov8监控交通流

介绍&#xff1a;YOLOv8 是一种开源目标检测算法&#xff08;模型&#xff09;&#xff0c;是 YOLO(You Only Look Once) 系列算法的最新版本。它使用单次预测框架对图像中的对象进行定位和分类。这种方法可以检测多个对象&#xff0c;并且速度更快&#xff0c;准确率更高。 参…

framework ‘CoreAudioTypes‘ not found

几天前我升级Xcode15之后遇到了这个问题。关于“CoreAudioTypes”的信息完全是误导。在我的例子中&#xff0c;原因是在删除一些旧代码时&#xff0c;我不小心删除了仍然需要的类。然而&#xff0c;在构建时弹出的唯一消息是关于“CoreAudioTypes”——当我恢复丢失的类时&…

一例Phorpiex僵尸网络变种的分析

概述 这是一例Phorpiex僵尸网络变种&#xff0c;通过NSIS打包&#xff0c;加载恶意dll(Flaminius.dll)&#xff0c;读取dat文件&#xff08;Preoral.dat&#xff09;&#xff0c;在内存解密并解压缩出一个Pe&#xff0c;创建同名傀儡进程并注入。通过可移动存储介质传播&#…

【BOSS直聘爬取系统功能介绍】

完整代码关注公众号 &#xff1a; 爬取网站&#xff1a;BOSS直聘&#xff1a;https://www.zhipin.com/ 难点 1. boss直聘不论什么岗位都只会展示10页数据&#xff0c;就算在网页里加到了11&#xff0c;内容也会和10一样。 2.多次访问会有验证码需要登录&#xff0c;这部分需…

短视频世上无人再似她:成都鼎茂宏升文化传媒公司

短视频世上无人再似她 —— 记忆中的光影传奇 在短视频盛行的今天&#xff0c;每一位创作者都在用镜头捕捉生活&#xff0c;记录世界&#xff0c;但有那么一位艺术家&#xff0c;她的作品如同夜空中最亮的星&#xff0c;即便是在信息洪流中&#xff0c;也依然闪耀着独一无二的…

jupyter_lab修改默认目录

1、配置jupyterlab和jupyternotebook的默认工作路径。 2、不废话&#xff0c;直接上步骤 在Jupyter Notebook或者cmd命令行中输入&#xff1a; jupyter notebook --generate-config jupyter-lab --generate-config生成配置文件“jupyter_notebook_config.py"和jupyter_la…

高通Android 11/12/13 通过包名设置默认launcher

背景&#xff1a;最近在封装供第三应用系统SDK 接口&#xff0c;遇到一个无法通过包名设置主launcher代码坑所以记录下。 涉及类roles.xml # <!---~ see com.android.settings.applications.defaultapps.DefaultHomePreferenceController~ see com.android.settings.appl…

重启服务器后node节点显示NotReady

场景&#xff1a;夜间进行了断电维护&#xff0c;重启后发现业务无法使用&#xff0c;检查发现一个node节点显示NotReady. 去到目标服务器查看kubelet服务未成功启动 journalctl -u kubelet 执行journalctl -u kubelet 查看日志发现提示&#xff1a; ailed to run Kubelet: run…

BFS和DFS优先搜索算法

1. BFS与DFS 1.1 BFS DFS即Depth First Search&#xff0c;深度优先搜索。它是一种图遍历算法&#xff0c;它从一个起始点开始&#xff0c;逐层扩展搜索范围&#xff0c;直到找到目标节点为止。 这种算法通常用于解决“最短路径”问题&#xff0c;比如在迷宫中找到从起点到终…

铁路机辆作业移动智能终端的特点是什么?

在铁路机辆作业的现代化进程中&#xff0c;移动智能终端以其独特的优势成为了不可或缺的装备。这些终端以其高度的便携性&#xff0c;使得工作人员能够随时随地处理各种作业任务&#xff0c;极大地提升了工作效率。它们具备出色的抗干扰性和高防护性&#xff0c;能够在复杂多变…

算法学习系列(六十一):树形DP

目录 引言一、没有上司的舞会二、树的重心三、树的最长路径四、树的中心 引言 关于这个树形 D P DP DP 代码其实都是那一套&#xff0c;核心还是在于思维上的难度&#xff0c;关键是这个思路你能不能想明白&#xff0c;想明白了就非常的简单&#xff0c;因为代码几乎长得都差…

LLM应用-prompt提示:让大模型总结生成思维导图

第一步&#xff1a;大模型生成markdown思维导图格式 例如&#xff1a;kimi 总结pdf文档案例&#xff1a; 生成的markdown格式&#xff1a; # 知识图谱的构建及应用 ## 一、知识图谱的构建 ### 1. 数据采集 - 来源&#xff1a;结构化数据库、半结构化网页、非结构化文本 - 预处…

PCIE V3.0物理层协议学习笔记

一、说明 PCI-Express(peripheral component interconnect express)是一种高速串行计算机扩展总线标准&#xff0c;它原来的名称为“3GIO”&#xff0c;是由英特尔在2001年提出的&#xff0c;旨在替代旧的PCI&#xff0c;PCI-X和AGP总线标准。 PCIe属于高速串行点对点双通道高…

8.11 矢量图层线要素单一符号使用二

文章目录 前言箭头&#xff08;Arrow&#xff09;QGis设置线符号为箭头(Arrow)二次开发代码实现 总结 前言 本章介绍矢量图层线要素单一符号中箭头&#xff08;Arrow&#xff09;的使用说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 箭头&#xff08;Arr…

证照之星是什么软件 证照之星哪个版本好用?证照之星支持哪些相机 证照之星XE免费版

许多人都需要使用证件照&#xff0c;为了满足这一需求&#xff0c;人们会使用照相机、手机、电脑等工具进行拍摄。除此之外&#xff0c;市面上还存在专门的证件照拍摄软件&#xff0c;比如证照之星。那么&#xff0c;各位小伙伴是否了解证照之星哪个版本好用&#xff0c;证照之…

如何利用3D可视化大屏提升信息展示效果?

老子云3D可视化平台https://www.laozicloud.com/ 引言 在信息爆炸的时代&#xff0c;如何有效地传达和展示信息成为了各行各业的一大挑战。传统的平面展示方式已经无法满足人们对信息展示的需求&#xff0c;3D可视化大屏应运而生&#xff0c;成为了提升信息展示效果的利器。本…

大模型相关内容的研究学习

大模型研究学习 1.大模型的“幻觉” 幻觉可以分为事实性幻觉和忠实性幻觉。 事实性幻觉&#xff0c;是指模型生成的内容与可验证的现实世界事实不一致。 比如问模型“第一个在月球上行走的人是谁&#xff1f;”&#xff0c;模型回复“Charles Lindbergh在1951年月球先驱任务…