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: es
  elasticsearch:
    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 {

    @Resource
    private lateinit var elasticsearchTemplate: ElasticsearchTemplate

    @Test
    fun 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 库中插入数据,如下代码:

    @Test
    fun 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 {

    @Resource
    private lateinit var elasticsearchTemplate: ElasticsearchTemplate

    @Test
    fun 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)
    }

    @Test
    fun testDelete() {
        //根据主键删除,例如删除主键 id = 1 的文档
        elasticsearchTemplate.delete("1", AlbumInfoDo::class.java)
    }

    @Test
    fun testGet() {
        //根据主键获取文档
        val result = elasticsearchTemplate.get("1", AlbumInfoDo::class.java)
        println(result)
    }

    @Test
    fun testUpdate() {
        //例如,修改 id = 1 的文档
        val id = 1
        val 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")).result
        println(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 {

    @Resource
    private lateinit var elasticsearchTemplate: ElasticsearchTemplate

    /**
     * 全文检索查询(match_all)
     */
    @Test
    fun 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)
     */
    @Test
    fun 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)
     */
    @Test
    fun 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) }
    }

    /**
     * 范围搜索
     */
    @Test
    fun 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 复合搜索
     */
    @Test
    fun 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 -> mc
                            mc.field("title").query("天气")
                        }
                    }
                    .should { s -> s
                        .matchAll { it }
                    }
                }
            }.build()
        val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)
        hits.forEach { println(it.content) }
    }

    /**
     * 排序 + 分页
     */
    @Test
    fun 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) }
    }

    @Test
    fun 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 {

    @Resource
    private lateinit var elasticsearchTemplate: ElasticsearchTemplate

    @Test
    fun 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, "连王思聪也变得低调老实了", "如今的王思聪,不仅交女友的质量下降,在网上也不再像以前那样随意喷这喷那。显然,资金的紧张让他低调了许多")
            )
        )
    }

    @Test
    fun suggestTest() {
        //模拟客户端输入的需要自动补全的字段
        val input = "今天"
        val limit = 10

        val 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 结构如下:

运行结果:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Optional用法

说明&#xff1a;Optional和Stream一样&#xff0c;是Java8引入的特性&#xff0c;本文介绍Optional的几个实际用法。Steam流使用&#xff0c;参考下面这篇文章&#xff1a; Stream流使用 使用 1.保证值存在 // 1.保证值存在&#xff0c;pageNumber&#xff0c;pageSizeInte…

PR标题模板,视频内容要点提示文字列表模板剪辑素材

Premiere Pro的要点列表标题模板。 主要特点&#xff1a; 可以无限制地添加任意数量的列表项。 使用直观的控件轻松自定义列表的各个方面。只需点击几下&#xff0c;即可调整颜色、大小、位置等。 轻松调整颜色&#xff0c;享受完全的创作自由。 可以轻松调整列表项之间的间距…

mybatis-plus之数据源切换事务失效问题

为什么存在数据源切换和食物时效问题&#xff1f; 由于业务数据来源不同 需要配置多个数据源来进行数据的查询 编辑等操作 这一切换业务对数据的一致性要求很高那就要保证ACID啦 也就是数据的有效性 要么是成功的 要么是失败的。 数据源切换采用mybatisplus支持 多数据源配置&a…

Linux下VMamba 环境复现+环境测试

# 1. 创建自己的虚拟环境 conda create -n VMamba python3.10.13 conda activate VMamba # 2. cuda-11.8 conda install cudatoolkit11.8 -c nvidia # 3. torch torchvision torchaudio 与 官网命令一致 pip install torch2.1.1 torchvision0.16.1 torchaudio2.1.1 --index-url…

自集成式 HTTP 代理方案

前言 大部分程序员&#xff0c;想必都会有一个常用的抓包代理工具&#xff1b; 但在座的各位&#xff0c;可曾见过这样一款集成在 Web 应用中的代理工具&#xff1f; ​&#xff0c;时长00:45 它是明显区别于传统代理工具的&#xff0c;有以下特性&#xff1a; 零安装、零配…

解决AdaptiveAvgPool2d部署算子不支持问题

一、Pytorch中AdaptiveAvgPool2d函数详解 torch.nn.AdaptiveAvgPool2d()接受两个参数&#xff0c;分别为输出特征图的长和宽&#xff0c;其通道数前后不发生变化。如以下&#xff1a; self.global_avgpool nn.AdaptiveAvgPool2d(1) # 输出N*C*1*1 self.global_avgpool …

AcWing166. 数独-DFS剪枝与优化

题目 思路 思考问题&#xff1a;搜索顺序->考虑剪枝搜索顺序&#xff1a;先随意选择一个空格子&#xff0c;枚举该格子可填写的数字&#xff0c;当所有格子都填完的时候&#xff0c;说明可以退出了剪枝&#xff1a; 优化搜索顺序&#xff1a;随意选择一个空格子&#xff1a…

【讲解下iCloud如何高效利用】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

C++实战演练---负载均衡在线oj项目 || 编译服务模块设计

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 前言 上一篇预热文章简单说过我们的编写思路&#xff0c;首先要实现的是编译功能&#xff0c;那么在编译功能版块中&…

Java面试八股之float和double的区别

Java中float和double的区别 存储空间与精度&#xff1a; double&#xff1a;占据64位&#xff08;8字节&#xff09;存储空间&#xff0c;属于双精度浮点数。它可以提供较高的精度&#xff0c;通常能够精确表示大约15到17位十进制数字&#xff0c;适合用于需要较高精度计算或…

SSM【Spring SpringMVC Mybatis】—— Spring(二)

如果对于Spring的一些基础理论感兴趣可见&#x1f447; SSM【Spring SpringMVC Mybatis】—— Spring&#xff08;一&#xff09; 目录 1、Spring中bean的作用域 1.1 语法 1.2 四个作用域 2、Spring中bean的生命周期 2.1 bean的生命周期 2.2 bean的后置处理器 2.3 添加后…

upload-labs靶场通关详解(1-15)

1.pass-01 查看源代码 是js&#xff0c;属于前端校验 可以通过禁用js来上传文件 2.pass-02 根据提示是MIME绕过 MIME&#xff1a;是设定某种扩展名的文件 用一种应用程序来打开的方式类型&#xff0c;当该扩展名文件被访问的时候&#xff0c;浏览器会自动使用指定应用程序来…

OpenAI发布新品GPT-4o,电影《HER》演绎的世界真的来了!

5月14日&#xff0c;OpenAI宣布推出最新旗舰生成式AI模型GPT-4o&#xff0c;它可以实时处理音频、视觉、并对文本进行推理。可以说这是一种全新的交互模式&#xff0c;它完美复刻电影《Her》的世界&#xff0c;标志着人工智能全感知时代的到来。 GpuMall智算云 | 省钱、好用、…

swiper 点击事件失效问题

在刚开始使用是 swiper 时&#xff0c;点击事件有时失效&#xff0c;这些个问题的原因是&#xff1a;swiper设置looptrue时&#xff0c;会生成虚拟slide进行填充&#xff0c;对这些虚拟slide元素进行操作是无效的。 简单粗暴的方法就是将 loop 置为 false ....................…

JVM面试题:85道JVM虚拟机面试题及答案

面试题 1 .简述Java堆的结构&#xff1f;什么是堆中的永久代(Perm Gen space)? JVM整体结构及内存模型 试题回答参考思路&#xff1a; 1、堆结构 JVM的堆是运行时数据区&#xff0c;所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创建。对象所占的堆内存是由自…

开发测试必须知道的 10种 常见软件架构模式

你是否想知道企业大规模系统是如何设计的? 在软件开发开始之前&#xff0c;我们必须选择一个合适的架构&#xff0c;能提供所需的功能和质量特性。因此&#xff0c;在将架构应用到我们的设计之前&#xff0c;我们应该了解各种不同架构的特点。 01 什么是架构模式 根据维基百…

一文分享:抖音外卖城市合伙人如何申请合作?

在当今数字化时代&#xff0c;外卖和团购业务蓬勃发展&#xff0c;商家们纷纷寻求在多个平台上拓宽销售渠道&#xff0c;以获取更多的订单和利润&#xff0c;这也给创业者提供创来机会。在这其中&#xff0c;抖音外卖作为一股新势力&#xff0c;自然吸引了众多创业者的目光&…

解锁客户需求密码:银行业数据分析在业务决策中的关键作用

一、引言 在数字化和大数据时代的浪潮下&#xff0c;银行业正经历着前所未有的变革。作为数据分析领域的资深专家&#xff0c;我深知数据分析在银行业务发展中的重要性和价值。本文将从银行业数据分析的角度出发&#xff0c;深入探讨相关业务场景下的数据分析应用&#xff0c;…

斥巨资!韩国力撑芯片产业

KlipC报道&#xff1a;韩国为加强本国半导体产业竞争力&#xff0c;将推进一项超过10万亿韩元的支持计划。 大型科技公司微软、亚马逊和谷歌为了保持自己大型语言模型的竞争力&#xff0c;投入了大量的资金&#xff0c;全球对可生成AI应用的需求在不断增长&#xff0c;市场上对…

Vision Mamba 代码调试---Pycharm+AutoDL

《AutoDL使用手册》 1. 服务器租用与配置 先上项目链接&#xff1a; GitHub - hustvl/Vim: Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 1.1 服务器租用与配置 根据环境要求&#xff0c;去租一个服务器&#xff1a;AutoDL算…