Docker Compose安装milvus向量数据库单机版-milvus基本操作

news2024/7/4 23:44:34

目录

  • 安装Ubuntu 22.04 LTS
  • 在power shell启动milvus容器
    • 安装docker desktop
    • 下载yaml文件
    • 启动milvus容器
    • Milvus管理软件Attu
  • python连接milvus
    • 配置
    • 下载wget
    • 示例
      • 导入必要的模块和类
      • 与Milvus数据库建立连接
      • 创建名为"hello_milvus"的Milvus数据表
      • 插入数据
      • 创建索引
      • 基于向量相似性的搜索
      • 基于标量过滤条件的查询操作
      • 基于向量相似性和标量过滤条件的混合搜索
      • 基于主键值删除数据记录
      • 删除Milvus数据表
  • 停止所有docker容器
  • 未完待续

安装Ubuntu 22.04 LTS

以管理员身份运行powershell
在这里插入图片描述

wsl
wsl --list --online

Ubuntu 22.04 LTS可以不装,wsl必须更新。。。

wsl --install -d Ubuntu-22.04
wsl.exe --update

如果 操作超时 ,可以试试开代理。
在这里插入图片描述
重启电脑。。。
在这里插入图片描述
设置用户名、密码
在这里插入图片描述

在power shell启动milvus容器

安装docker desktop

https://hub.docker.com/

在这里插入图片描述
在这里插入图片描述
重启电脑。。。
在这里插入图片描述
在这里插入图片描述

下载yaml文件

power shell输入以下命令,下载yaml文件到指定目录,并重命名为docker-compose.yml

Invoke-WebRequest -Uri https://github.com/milvus-io/milvus/releases/download/v2.3.2/milvus-standalone-docker-compose.yml -OutFile E:\codes\milvus\docker-compose.yml

或者
点击一下链接直接下载
https://github.com/milvus-io/milvus/releases/download/v2.3.2/milvus-standalone-docker-compose.yml

启动milvus容器

cd E:\codes\milvus
docker-compose up -d

在这里插入图片描述
a few moments later。。。

docker compose ps

在这里插入图片描述
在这里插入图片描述

Milvus管理软件Attu

https://github.com/zilliztech/attu/releases
https://github.com/zilliztech/attu/releases/download/v2.3.2/attu-Setup-2.3.2.exe
在这里插入图片描述
在这里插入图片描述

python连接milvus

https://milvus.io/docs/example_code.md

配置

python环境

conda create -n milvus-env python=3.9
conda env list
conda activate milvus-env
pip install ipykernel -i https://pypi.tuna.tsinghua.edu.cn/simple/
python -m ipykernel install --name milvus-env
pip install pymilvus==2.3.2 -i https://pypi.tuna.tsinghua.edu.cn/simple/

下载wget

https://eternallybored.org/misc/wget/
wget.exe文件放到C:\Windows\System32

!wget https://raw.githubusercontent.com/milvus-io/pymilvus/master/examples/hello_milvus.py

示例

下面演示如何使用PyMilvus库连接到Milvus数据库,创建数据表,插入数据,创建索引,进行搜索、查询、分页查询,以及删除数据表等操作。

导入必要的模块和类

  • connections: 这是PyMilvus库的模块,用于建立与Milvus数据库的连接。

  • utility: 这也是PyMilvus库的模块,包含了一些实用的函数,用于执行Milvus的管理和操作。

  • FieldSchema, CollectionSchema, DataType, Collection: 这些类属于PyMilvus库,用于定义数据表的字段结构、数据类型、数据表模式和执行数据表操作。

变量fmtsearch_latency_fmtnum_entitiesdim:用于格式化输出和指定示例中使用的实体数量和维度。

import time

import numpy as np
from pymilvus import (
    connections,
    utility,
    FieldSchema, CollectionSchema, DataType,
    Collection,
)

fmt = "\n=== {:30} ===\n"
search_latency_fmt = "search latency = {:.4f}s"
num_entities, dim = 3000, 8

与Milvus数据库建立连接

与Milvus数据库建立连接并检查是否存在名为"hello_milvus"的数据表

  • 使用connections模块的connect函数来建立连接,指定了连接别名(“default”)以及Milvus服务器的主机地址和端口。在这里,连接别名是"default",表示使用默认的连接配置,Milvus服务器的地址是"localhost",端口是"19530"。
  • 使用utility模块的has_collection函数检查是否存在名为"hello_milvus"的数据表。如果数据表存在,它将返回True,否则返回False
print(fmt.format("start connecting to Milvus"))
connections.connect("default", host="localhost", port="19530")

has = utility.has_collection("hello_milvus")
print(f"Does collection hello_milvus exist in Milvus: {has}")

output:

=== start connecting to Milvus     ===

Does collection hello_milvus exist in Milvus: False

创建名为"hello_milvus"的Milvus数据表

创建名为"hello_milvus"的Milvus数据表,并定义数据表的字段结构和模式。

  1. fields: 这是一个包含了数据表字段结构的列表。每个字段由FieldSchema对象表示,其中包括字段名称、数据类型、是否是主键、主键是否自动生成、以及其他相关属性。在这个示例中,定义了三个字段:

    • “pk” 字段是主键字段,数据类型为VARCHAR,主键不自动生成(auto_id=False),并且设置最大长度为100字符。
    • “random” 字段是双精度浮点数字段,数据类型为DOUBLE。
    • “embeddings” 字段是浮点向量字段,数据类型为FLOAT_VECTOR,并且指定向量维度(dim)为之前定义的dim变量的值(8维)。
  2. schema: 这是一个CollectionSchema对象,它用于定义数据表的模式。schema包含了字段结构和数据表的描述信息。

  3. 创建Milvus数据表:使用Collection对象来创建数据表,指定数据表的名称(“hello_milvus”),数据表模式(schema对象),以及一致性级别(“Strong”)。一致性级别用于控制数据表的数据一致性。

field namefield typeother attributesfield description
1“pk”VarCharis_primary=True , auto_id=False“primary field”
2“random”Double“a double field”
3“embeddings”FloatVectordim=8“float vector with dim 8”
fields = [
    FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=False, max_length=100),
    FieldSchema(name="random", dtype=DataType.DOUBLE),
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]

schema = CollectionSchema(fields, "hello_milvus is the simplest demo to introduce the APIs")

print(fmt.format("Create collection `hello_milvus`"))
hello_milvus = Collection("hello_milvus", schema, consistency_level="Strong")

插入数据

插入数据记录到Milvus数据表"hello_milvus"中

  1. entities: 这是一个包含要插入的数据记录的列表。数据记录按字段分组,其中每个字段的数据以列表的形式包含在entities列表中。具体描述如下:

    • 第一个子列表 [str(i) for i in range(num_entities)] 包含了主键字段 “pk” 的值,使用字符串表示。这些字符串是根据主键字段的定义生成的,因为auto_id设置为False,所以需要提供主键值。

    • 第二个子列表 rng.random(num_entities).tolist() 包含了双精度浮点数字段 “random” 的值,这些值是使用随机数生成器生成的,并转换为列表格式。

    • 第三个子列表 rng.random((num_entities, dim)) 包含了浮点向量字段 “embeddings” 的值,这些值是使用随机数生成器生成的,维度(dim)由之前定义的变量确定。

  2. 使用Milvus数据表的insert方法将数据记录插入到数据表中。插入后,insert_result将包含插入操作的结果信息,如主键值等。

  3. flush(): 刷新数据表,确保插入的数据被持久化保存到磁盘中。在Milvus中,数据通常在内存中进行操作,然后通过flush操作将其持久保存。

print(fmt.format("Start inserting entities"))
rng = np.random.default_rng(seed=19530)
entities = [
    # provide the pk field because `auto_id` is set to False
    [str(i) for i in range(num_entities)],
    rng.random(num_entities).tolist(),  # field random, only supports list
    rng.random((num_entities, dim)),    # field embeddings, supports numpy.ndarray and list
]

insert_result = hello_milvus.insert(entities)

hello_milvus.flush()
print(f"Number of entities in Milvus: {hello_milvus.num_entities}")  # check the num_entities

output:

=== Start inserting entities       ===

Number of entities in Milvus: 3000

创建索引

在Milvus数据表"hello_milvus"的浮点向量字段"embeddings"上创建一个IVF_FLAT索引。

  1. index: 这是一个字典,包含了索引的相关参数。在这个示例中,定义了以下索引参数:

    • “index_type”: 指定了索引类型为 “IVF_FLAT”,这是一种基于倒排列表的索引类型,适用于浮点向量字段。

    • “metric_type”: 指定了距离度量类型为 “L2”,表示使用欧几里德距离来衡量向量之间的相似性。

    • “params”: 这是一个包含索引参数的字典,包括 “nlist” 参数,它指定了索引的列表数量,这里设置为128。

  2. 使用Milvus数据表的create_index方法,在名为"embeddings"的字段上创建了指定的IVF_FLAT索引。参数 “embeddings” 表示要在哪个字段上创建索引,而 index 字典包含了索引的配置信息。

通过这段代码,IVF_FLAT索引被创建在"hello_milvus"数据表的"embeddings"字段上,用于加速相似性搜索操作。索引的创建有助于提高查询性能,特别是对于包含大量浮点向量数据的场景。索引类型和参数可以根据具体需求进行调整和优化。

print(fmt.format("Start Creating index IVF_FLAT"))
index = {
    "index_type": "IVF_FLAT",
    "metric_type": "L2",
    "params": {"nlist": 128},
}

hello_milvus.create_index("embeddings", index)

基于向量相似性的搜索

  1. hello_milvus.load(): 将数据表"hello_milvus"中的数据加载到内存中,以便后续的搜索和查询操作可以更快地执行。在Milvus中,数据通常是存储在磁盘上的,加载数据到内存可以提高查询性能。

  2. vectors_to_search = entities[-1][-2:]: 从entities中获取浮点向量字段"embeddings"的值。entities[-1]表示最后一个子列表,而[-2:]表示获取该子列表的最后两个元素,即浮点向量数据。这些向量数据将用于相似性搜索。

  3. search_params: 这是一个包含搜索参数的字典。在这个示例中,定义了以下参数:

    • “metric_type”: 指定了距离度量类型为 “L2”,表示使用欧几里德距离来衡量向量之间的相似性。

    • “params”: 这是一个包含搜索参数的字典,包括 “nprobe” 参数,它指定了搜索时的候选集数量,这里设置为10。

  4. search(): 使用Milvus数据表的search方法执行相似性搜索操作。参数包括搜索的向量数据(vectors_to_search)、搜索的字段名称(“embeddings”)、搜索参数(search_params)、返回结果的数量限制(limit=3),以及要返回的输出字段(“random”)。搜索操作将返回与搜索向量相似的数据记录。

  5. 遍历搜索结果,遍历每个搜索结果中的数据记录。

print(fmt.format("Start loading"))
hello_milvus.load()

# -----------------------------------------------------------------------------
# search based on vector similarity
print(fmt.format("Start searching based on vector similarity"))
vectors_to_search = entities[-1][-2:]
search_params = {
    "metric_type": "L2",
    "params": {"nprobe": 10},
}

start_time = time.time()
result = hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, output_fields=["random"])
end_time = time.time()

for hits in result:
    for hit in hits:
        print(f"hit: {hit}, random field: {hit.entity.get('random')}")
print(search_latency_fmt.format(end_time - start_time))

output:

=== Start loading                  ===


=== Start searching based on vector similarity ===

hit: id: 2998, distance: 0.0, entity: {'random': 0.9728033590489911}, random field: 0.9728033590489911
hit: id: 1262, distance: 0.08883658051490784, entity: {'random': 0.2978858685751561}, random field: 0.2978858685751561
hit: id: 1265, distance: 0.09590047597885132, entity: {'random': 0.3042039939240304}, random field: 0.3042039939240304
hit: id: 2999, distance: 0.0, entity: {'random': 0.02316334456872482}, random field: 0.02316334456872482
hit: id: 1580, distance: 0.05628091096878052, entity: {'random': 0.3855988746044062}, random field: 0.3855988746044062
hit: id: 2377, distance: 0.08096685260534286, entity: {'random': 0.8745922204004368}, random field: 0.8745922204004368
search latency = 0.3700s

基于标量过滤条件的查询操作

基于标量过滤条件的查询操作,以及查询结果的分页操作。

  1. hello_milvus.query(expr="random > 0.5", output_fields=["random", "embeddings"]): 使用Milvus数据表的query方法执行查询操作。筛选"random > 0.5"的数据记录,返回的输出字段(“random"和"embeddings”)。

  2. result 是一个包含查询结果的列表,每个元素是一个包含查询结果字段的字典。在这里,打印了第一个查询结果的信息。

  3. hello_milvus.query(expr="random > 0.5", limit=4, output_fields=["random"]): 分页查询,限制结果数量为4条。参数 limit=4 指定了返回结果的最大数量,只返回满足条件的前4条数据,并指定了要返回的输出字段为 “random”。

  4. hello_milvus.query(expr="random > 0.5", offset=1, limit=3, output_fields=["random"]): 另一个分页查询,设置了偏移量 offset=1 和限制结果数量 limit=3,以返回满足条件的数据记录的第2到第4条数据,并同样指定了要返回的输出字段为 “random”。

print(fmt.format("Start querying with `random > 0.5`"))

start_time = time.time()
result = hello_milvus.query(expr="random > 0.5", output_fields=["random", "embeddings"])
end_time = time.time()

print(f"query result:\n-{result[0]}")
print(search_latency_fmt.format(end_time - start_time))

# -----------------------------------------------------------------------------
# pagination
r1 = hello_milvus.query(expr="random > 0.5", limit=4, output_fields=["random"])
r2 = hello_milvus.query(expr="random > 0.5", offset=1, limit=3, output_fields=["random"])
print(f"query pagination(limit=4):\n\t{r1}")
print(f"query pagination(offset=1, limit=3):\n\t{r2}")

output:

=== Start querying with `random > 0.5` ===

query result:
-{'random': 0.6378742006852851, 'embeddings': [0.20963514, 0.39746657, 0.12019053, 0.6947492, 0.9535575, 0.5454552, 0.82360446, 0.21096309], 'pk': '0'}
search latency = 0.4006s
query pagination(limit=4):
	[{'random': 0.6378742006852851, 'pk': '0'}, {'random': 0.5763523024650556, 'pk': '100'}, {'random': 0.9425935891639464, 'pk': '1000'}, {'random': 0.7893211256191387, 'pk': '1001'}]
query pagination(offset=1, limit=3):
	[{'random': 0.5763523024650556, 'pk': '100'}, {'random': 0.9425935891639464, 'pk': '1000'}, {'random': 0.7893211256191387, 'pk': '1001'}]

基于向量相似性和标量过滤条件的混合搜索

  1. hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, expr="random > 0.5", output_fields=["random"]): 使用Milvus数据表的search方法执行混合搜索操作。参数包括搜索的向量数据(vectors_to_search)、搜索的字段名称(“embeddings”)、搜索参数(search_params),限制结果数量(limit=3),以及标量过滤条件表达式(expr="random > 0.5")。混合搜索操作将返回同时满足向量相似性和标量条件的数据记录。

  2. 遍历混合搜索结果,遍历每个搜索结果中的数据记录。

基于向量相似性和标量过滤条件的混合搜索操作,检索同时满足这两种条件的数据记录,并输出了混合搜索结果。混合搜索可用于更精确地筛选满足多个条件的数据记录。

print(fmt.format("Start hybrid searching with `random > 0.5`"))

start_time = time.time()
result = hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, expr="random > 0.5", output_fields=["random"])
end_time = time.time()

for hits in result:
    for hit in hits:
        print(f"hit: {hit}, random field: {hit.entity.get('random')}")
print(search_latency_fmt.format(end_time - start_time))

output:

=== Start hybrid searching with `random > 0.5` ===

hit: id: 2998, distance: 0.0, entity: {'random': 0.9728033590489911}, random field: 0.9728033590489911
hit: id: 747, distance: 0.14606499671936035, entity: {'random': 0.5648774800635661}, random field: 0.5648774800635661
hit: id: 2527, distance: 0.1530652642250061, entity: {'random': 0.8928974315571507}, random field: 0.8928974315571507
hit: id: 2377, distance: 0.08096685260534286, entity: {'random': 0.8745922204004368}, random field: 0.8745922204004368
hit: id: 2034, distance: 0.20354536175727844, entity: {'random': 0.5526117606328499}, random field: 0.5526117606328499
hit: id: 958, distance: 0.21908017992973328, entity: {'random': 0.6647383716417955}, random field: 0.6647383716417955
search latency = 0.3875s

基于主键值删除数据记录

  1. insert_result.primary_keys: 从之前插入数据的结果对象insert_result中获取了插入操作生成的主键值(PK)。这些主键值被保存在primary_keys属性中。

  2. expr = f'pk in ["{ids[0]}" , "{ids[1]}"]': 使用主键值来指定要删除的数据记录。

  3. hello_milvus.query(expr=expr, output_fields=["random", "embeddings"]): 使用Milvus数据表的query方法执行查询操作,以验证删除操作前的查询结果。查询操作使用之前构建的布尔表达式expr,并指定要返回的输出字段为 “random” 和 “embeddings”。

  4. hello_milvus.delete(expr): 使用Milvus数据表的delete方法执行删除操作,根据之前构建的布尔表达式expr删除满足条件的数据记录。

  5. hello_milvus.query(expr=expr, output_fields=["random", "embeddings"]): 再次使用query方法执行查询操作,以验证删除操作后的查询结果。由于之前的数据记录已经被删除,查询结果应该为空。

ids = insert_result.primary_keys

expr = f'pk in ["{ids[0]}" , "{ids[1]}"]'
print(fmt.format(f"Start deleting with expr `{expr}`"))

result = hello_milvus.query(expr=expr, output_fields=["random", "embeddings"])
print(f"query before delete by expr=`{expr}` -> result: \n-{result[0]}\n-{result[1]}\n")

hello_milvus.delete(expr)

result = hello_milvus.query(expr=expr, output_fields=["random", "embeddings"])
print(f"query after delete by expr=`{expr}` -> result: {result}\n")

output:

=== Start deleting with expr `pk in ["0" , "1"]` ===

query before delete by expr=`pk in ["0" , "1"]` -> result: 
-{'embeddings': [0.20963514, 0.39746657, 0.12019053, 0.6947492, 0.9535575, 0.5454552, 0.82360446, 0.21096309], 'pk': '0', 'random': 0.6378742006852851}
-{'embeddings': [0.52323616, 0.8035404, 0.77824664, 0.80369574, 0.4914803, 0.8265614, 0.6145269, 0.80234545], 'pk': '1', 'random': 0.43925103574669633}

query after delete by expr=`pk in ["0" , "1"]` -> result: []

删除Milvus数据表

使用utility模块中的drop_collection函数,删除名为"hello_milvus"的Milvus数据表(集合)。删除数据表会彻底删除其中的所有数据记录和索引,并释放相关资源。

这个操作可以用于在不再需要数据表时释放资源和空间。

print(fmt.format("Drop collection `hello_milvus`"))
utility.drop_collection("hello_milvus")

停止所有docker容器

docker stop $(docker ps -q)

未完待续

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

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

相关文章

docker容器技术基础入门

docker容器技术基础入门 容器(Container) 容器是一种基础工具;泛指任何可以用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳、储存、运输物品;物体可以被放置在容器中,而容器则可以保护内容物;容器…

AVL树性质和实现

AVL树 AVL是两名俄罗斯数学家的名字,以此纪念 与二叉搜索树的区别 AVL树在二叉搜索树的基础上增加了新的限制:需要时刻保证每个树中每个结点的左右子树高度之差的绝对值不超过1 因此,当向树中插入新结点后,即可降低树的高度&…

数据结构:AVL树的实现和全部图解

文章目录 为什么要有AVL树什么是AVL树AVL树的实现元素的插入平衡因子的更新AVL树的旋转 AVL树的检查完整实现 本篇总结的是AVL树中的全部内容,配有详细的图解过程 为什么要有AVL树 前面对map/multimap/set/multiset进行了简单的介绍,在其文档介绍中发现…

计算机毕业设计java+springboot+vue的旅游攻略平台

项目介绍 本系统结合计算机系统的结构、概念、模型、原理、方法,在计算机各种优势的情况下,采用JAVA语言,结合SpringBoot框架与Vue框架以及MYSQL数据库设计并实现的。员工管理系统主要包括个人中心、用户管理、攻略管理、审核信息管理、积分…

Go 接口-契约介绍

Go 接口-契约介绍 文章目录 Go 接口-契约介绍一、接口基本介绍1.1 接口类型介绍1.2 为什么要使用接口1.3 面向接口编程1.4 接口的定义 二、空接口2.1 空接口的定义2.2 空接口的应用2.2.1 空接口作为函数的参数2.2.2 空接口作为map的值 2.3 接口类型变量2.4 类型断言 三、尽量定…

Day22力扣打卡

打卡记录 替换子串得到平衡字符串(滑动窗口) 链接 由于是以后统计替换的子串,不可以直接使用hash表统计的每个次数大于 n / 4 的字符,再将其次数减去平衡数来得到答案,根据字符串的连贯性,使用 滑动窗口 …

MySQL 8.0 如何修改密码安全策略!!!

目录 安全策略参数和常见等级:1.Mysql8.X常见安全策略参数指定密码的强度验证等级validate_password.policy 取值: 解决步骤1.登录mysql2.修改安全策略(1)语法如下:(2)修改完可以看一下: 3.改完密码策略,就可以根据自己修改的策略&#xff0c…

pytorch复现_UNet

什么是UNet U-Net由收缩路径和扩张路径组成。收缩路径是一系列卷积层和汇集层,其中要素地图的分辨率逐渐降低。扩展路径是一系列上采样层和卷积层,其中特征地图的分辨率逐渐增加。 在扩展路径中的每一步,来自收缩路径的对应特征地图与当前特征…

什么是分治算法?

分治算法(divide and conquer algorithm)是指把大问题分割成多个小问 题,然后把每个小问题分割成多个更小的问题,直到问题的规模小到能够 轻易解决。这种算法很适合用递归实现,因为把问题分割成多个与自身相 似的小问题正对应递归情况&#x…

Java —— 类和对象(一)

目录 1. 面向对象的初步认知 1.1 什么是面向对象 1.2 面向对象与面向过程 2. 类定义和使用 2.1 认识类 2.2 类的定义格式 3. 类的实例化(如何产生对象) 3.1 什么是实例化 3.2 访问对象的成员 3.3 类和对象的说明 4. this引用 4.1 为什么要有this引用 4.2 什么是this引用 4.3 th…

无线发射芯片解决方案在智能家居中的应用

随着物联网的发展,智能家居已经成为一个热门话题。智能家居利用无线技术来实现设备之间的互联互通,提供更智能、更便利的生活体验。无线发射芯片解决方案在智能家居中扮演着关键的角色,它们为智能家居设备之间的通信提供了稳定、高效的连接&a…

stm32f103+HC-SR04+ssd1306实现超声波测距

🙌秋名山码民的主页 😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 获取源码,添加WX 目录 前言HC…

【江协科技-用0.96寸OLED播放知名艺人打篮球视频】

Python进行视频图像处理,通过串口发送给stm32,stm32接收数据,刷新OLED进行显示。 步骤: 1.按照接线图连接好硬件 2.把Keil工程的代码下载到STM32中 3.运行Python代码,通过串口把处理后的数据发送给STM32进行显示 …

Spark 新特性+核心回顾

Spark 新特性核心 本文来自 B站 黑马程序员 - Spark教程 :原地址 1. 掌握Spark的Shuffle流程 1.1 Spark Shuffle Map和Reduce 在Shuffle过程中,提供数据的称之为Map端(Shuffle Write)接收数据的称之为Reduce端(Sh…

Leetcode刷题详解——组合

1. 题目链接:77. 组合 2. 题目描述: 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n 4, k 2 输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[…

vue3拖拽排序——vuedraggable

文章目录 安装代码效果拖拽前拖拽时拖拽后 vue3 的拖拽排序博主用的是 vuedraggable 安装 安装 npm i vuedraggable4.1.0 --save 引用 import Draggable from vuedraggable;代码 html <van-checkbox-group v-model"dataMap.newsActionChecked"><van-cell…

LazyVim: 将 Neovim 升级为完整 IDE | 开源日报 No.67

curl/curl Stars: 31.5k License: NOASSERTION Curl 是一个命令行工具&#xff0c;用于通过 URL 语法传输数据。 核心优势和关键特点包括&#xff1a; 可在命令行中方便地进行数据传输支持多种协议 (HTTP、FTP 等)提供丰富的选项和参数来满足不同需求 kubernetes/ingress-n…

项目中登录验证码怎么做才合理

唠嗑部分 今天我们来聊聊项目实战中登录验证码如何做比较合理&#xff0c;首先我们聊以下几个问题 1、登录时验证码校验是否必要&#xff1f; 答案当然是很有必要的&#xff0c;因为用户登录行为会直接影响数据库&#xff0c;如果没有某些防范措施&#xff0c;有恶意用户暴力…

NOIP2023模拟12联测33 A. 构造

NOIP2023模拟12联测33 A. 构造 文章目录 NOIP2023模拟12联测33 A. 构造题目大意思路code 题目大意 构造题 思路 想一种构造方法&#xff0c;使得 y y y 能够凑成尽可能多的答案 第一行 x y r y ⋯ r xyry \cdots r xyry⋯r 第二行 r y x y ⋯ x ryxy \cdots x ryxy⋯x …

基于SSM的出租车管理系统

基于SSM的出租车管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 登录界面 管理员界面 驾驶员界面 摘要 基于SSM&#xff08;Spring、Spring MVC、My…