Neo4j 与 Cypher 基础

更好的阅读体验 \huge{\color{red}{更好的阅读体验}} 更好的阅读体验

简介


Neo4j 是用 Java 实现的开源 NoSQL 图数据库。从2003年开始开发,2007年正式发布第一版,其源码托管于 GitHub。

与常见的关系型数据库不同,Neo4j 基于图图结构来表示和存储数据,并提供了申明式的查询语言 Cypher 来处理图数据。Neo4j 实现了专业数据库级别的图数据模型的存储,提供了完整的数据库特性,包括 ACID 事务的支持、集群的支持、备份和故障转移等。

Neo4j 作为图数据库中的代表产品,已经在众多的行业项目中进行了应用,如:网络管理、软件分析、组织和项目管理、社交项目等方面。


安装


Docker 部署


这里为了便于练习,我将其使用 Docker 部署到了我滴云服务器上,参考 Docker部署,其他部署方式参考。

首先拉取镜像(可以指定版本):

docker pull neo4j:4.4.5

然后编写一个简单的运行脚本 run.sh

#!/bin/bashdocker run \-d \--restart=always \--name neo4j \-p 7474:7474 \-p 7687:7687 \-v $HOME/docker/neo4j/data:/data \neo4j:4.4.5

然后运行脚本部署即可,browser 管理端口为 7474


Browser


Browser 端是 Neo4j 提供的一个图形用户界面(GUI)工具,用于管理和操作 Neo4j 图数据库。

浏览器打开:http://服务器地址:7474 即可访问。

如果没有在启动容器时指定密码,登录的默认密码为 neo4j首次登录后需要重设密码

不出意外的,便能看到如下界面,建议想要快速入门的话直接跟着官方教程走一遍:

image-20230924162531006

Browser 端支持:

  • Cypher 语言支持:允许用户编写和执行 Cypher 语句,支持对数据库中的节点和关系进行查询或编辑操作。
  • 图形可视化:支持节点和关系的可视化布局,能够更直观地体现和反映图数据库中的数据模型和关系。
  • 图形分析:提供了一些图形分析功能,如路径查找、社区检测和聚类分析等。
  • 用户管理:管理 Neo4j 数据库的用户和权限,创建和管理用户账号,分配不同的角色和权限,以控制对数据库的访问和操作。

Cypher-shell


Cypher-shellNeo4j 提供的官方命令行工具,用于执行 Cypher 语言。

使用如下命令进行连接:

cypher-shell -u <用户名> -p <密码> -a <数据库地址>

如果是 Docker 部署,进入容器操作即可:

docker exec -it <容器名> cypher-shell -u <用户名> -p <密码>

退出 Cypher-shell

:exit

Cypher 基础语法


Cypher 是用于图形数据库 Neo4j 的查询语言,它用于在图形数据库中进行数据检索和操作。Cypher 的语法简洁而直观,旨在提供一种易于理解和使用的方式来查询和操作图形数据。

注意

  • CQL 与关系型数据库中的 SQL,一些关键词来源于 SQL,比如:CREATEWHERERETURN 等。
  • CQL 关键字大小写不敏感,也使用 ; 分割多条查询语句。

数据结构


在学习 Cypher 语法前,首先需要了解 Neo4j 数据库的数据结构。

如果你在 Browser 端尝试运行了 Try Neo4j with live data 教程中的第一段代码,你会看到如下界面:

image-20230924163019460

如图所示,Neo4j 中采用节点、属性、关系、标签来存储数据,即右半部分出现的图谱。

  • 节点:
    • 节点是图数据模型的基本单元,用于存储实体数据。
    • 例如,在上图中,演员、电影都是节点,其中每个节点都有对应的属性。
    • 可以将一个节点理解为关系型数据库表中的一条数据,其字段对应节点的属性。
  • 关系:
    • 关系用于表示节点之间的连接或关联,具有一个类型(Type),用于描述节点之间的关系。
    • 关系有且只有一个类型,且必须声明其开始节点和结束节点以及指向。
    • 关系可以自我循环引用,但是两头永远不能为空。
  • 属性:
    • 节点和关系都可以有属性,它是由键值对组成的。
    • 属性可以是基本数据类型(例如字符串、整数、浮点数等)或复杂数据类型(例如数组、日期等)。
    • 节点的属性可以理解为关系型数据库中的字段。关系中的属性进一步的明确了关系。
  • 标签:
    • 标签是对节点的分类,这样使得构建 Neo4j 数据模型更加简单。
    • 在上面的电影案例中,MoviePerson 就是标签。

数据库操作


创建数据库:

CREATE DATABASE name;

删除数据库:

DROP DATABASE name;

修改数据库:

ALTER DATABASE name;

Neo4j 社区版不支持创建、删除和修改数据库,即上面的三个命令社区版用不鸟🤡,只能使用默认的 neo4jsystem 数据库。

查看所有数据库:

SHOW DATABASES;

打开数据库:

START DATABASE name;

关闭数据库:

STOP DATABASE name;

社区版只能同时运行一个数据库实例,如果存在正在运行的实例则启动失败🤡,想同时管理多个还是用企业版吧(


CREATE


创建节点


使用 CREATE 命令来创建节点:

CREATE (n); // 创建一个节点,没有任何标签和属性

创建一个标签为 DOG 的节点:

CREATE (n:DOG);

支持存在多个标签:

CREATE (n:ANIMAL:DOG);

添加属性:

CREATE (n:DOG {name: "LYS", age: 14});

创建多个节点:

CREATE (n:DOG {name: "LYS", age: 14}), (m:CAT {name: "Hiiro", age: 17});

nm 只是节点的变量名,在同一条创建语句中节点的变量名不能相同,节点的变量名不会影响后续的查询。

当然也可以不加变量名:

CREATE (:DOG {name: "LYS", age: 14}), (:CAT {name: "Hiiro", age: 17});

创建关系


创建两个节点的同时创建关系:

CREATE (n:DOG {name: "LYS", age: "14"}) -[r:IN_FAN]-> (m:CAT {name: "Hiiro", age: "17"});

也可以反向创建关系:

CREATE (n:DOG {name: "LYS", age: "14"}) <-[r:out_FAN]- (m:CAT {name: "Hiiro", age: "17"});

关系也可以设置属性:

CREATE (n:DOG {name: "LYS", age: "14"}) -[r:IN_FAN {action: "watch live any time"}]-> (m:CAT {name: "Hiiro", age: "17"});

可以一次性直接创建一条路径:

CREATE (n:DOG {name: "LYS"}) -[:IN_FAN] -> (i:CAT {name: "Hiiro"}) -[:WORK_FOR]-> (m:MOUSE {name: "ChenRay"});

注意:在 Cypher 中,节点之间的关系在创建后不能修改,想要修改只能删除原有关系再重新创建新的关系。


RETURN


RETURN 语句可以返回 Cypher 的执行结果。

比如,我们创建完节点后直接返回:

CREATE (n:DOG {name: "LYS", age: "14"}) RETURN n;

也可以返回我们创建好的关系:

CREATE (n:DOG {name: "LYS", age: "14"}) -[:IN_FAN]-> (m:CAT {name: "Hiiro", age: "17"}) RETURN n, m;

也可以给返回的结果取别名:

CREATE (n:DOG {name: "LYS", age: "14"})
RETURN n.name AS LYS_NAME;

更多关于 RETURN 的用法将在下文陆续提到。


MATCH


首先我们导入一些数据用于后面的示例:

MATCH(n) DETACH DELETE n;
CREATE(n:DOG {name: "LYS", age: 14}) -[:LOVER]-> (:BIRD {name: "Astesia", age: 13}) -[:FRIEND]-> (m:CAT {name: "Hiiro", age: 17}), (n) -[:FAN_OF]-> (m), (c:MOUSE {name: "ChenRay", age: 114}) -[:LOVER]-> (:DOG {name: "LexBurner", age: 514}), (c) -[:FAN_OF]-> (m), (n) -[:WORK_FOR]-> (p:PLANTFROM {name: "BILIBILI"}) -[:HAVE]-> (:DOG {name: "UPs", age: 1919}), (p) -[:BELONGS_to]-> (c);
CREATE(:WORKER:DOG {name: "打工人", age: 60}) -[:WORK_FOR]-> (:BOSS:DOG {name: "老板", age: 20}), (:DOG {name: "黑心老板", age: 0}), (:DOG {name: "黑心老板", age: 1}), (:DOG {name: "伤心打工人", age: 520}), (:DOG {name: "快乐打工人", age: 520}) -[:WORK_FOR]-> (:DOG {name: "良心老板", age: 1314});

条件查询


查询所有的节点及其关系:

MATCH(n) 
RETURN n;

根据标签查询节点,例如查询所有标签包含 DOG 的节点::

MATCH(n: DOG)
RETURN n;

我们在上面提到过关系的创建,现在我们可以通过 MATCHCREATE 查询节点并创建关系了:

MATCH(n:CAT) , (m:PLANTFROM)
CREATE (n) -[:WORK_FOR]-> (m)
RETURN n, m;

使用上述语句创建关系时,必须注意查询结果集的大小,若存在多个符合条件的节点,则会对结果集中所有的节点创建对应关系。

查询所有与某节点有关系的节点:

MATCH (n:CAT {name: "Hiiro"})--(m)
RETURN n, m;

根据关系查询,例如查询关系为 WORK_FOR 的节点:

MATCH (n)--(WORK_FOR)
RETURN n;

-- 并没有指定方向,如需指定使用 --><--

MATCH (n)-->(WORK_FOR)
RETURN n;
MATCH (n)<--(WORK_FOR)
RETURN n;

查询两个节点的关系:

MATCH(n:DOG {name:"打工人"}) -[r]-> (m:DOG {name: "老板"})
RETURN type(r);

关系深度查询


六度分隔(Six Degrees of Separation)理论。

1967年,哈佛大学的心理学教授Stanley Milgram(1933~1984)想要描绘一个连结人与社区的人际连系网。做过一次连锁信实验,结果发现了“六度分隔”现象。简单地说:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过六个人你就能够认识任何一个陌生人。”

由于一个节点可能存在多个关系,如果想要查询一条关系路径,未免包含太多的可行路径,因此需要在指定的深度内进行查询,这个查询的过程类似于迭代加深搜索的过程。

在图数据库中进行关系深度查询时,可以使用 * 运算符来指定关系的深度:

MATCH (startNode)-[*<minDepth>..<maxDepth>]-(endNode)
RETURN startNode, endNode;

其中:

  • (startNode)(endNode) 是节点模式,用于指定起始节点和结束节点。
  • [*<minDepth>..<maxDepth>] 是关系模式,用于指定关系的深度范围。<minDepth> 表示最小深度,<maxDepth> 表示最大深度。可以根据需要省略其中一个值,或者两个值都省略。
    • 如果只指定 <minDepth>,则表示最小深度为该值,而没有最大深度限制。
    • 如果只指定 <maxDepth>,则表示最大深度为该值,而没有最小深度限制。
    • 如果同时指定 <minDepth><maxDepth>,则表示深度范围在最小深度和最大深度之间(包括最小深度和最大深度)。

例如,查询从某个节点出发,关系深度为 1 ∼ 2 1 \sim 2 12 的节点:

MATCH (n:CAT {name:"Hiiro"}) -[*1..2]->(m)
RETURN *;

也可以写成:

MATCH (n:CAT {name:"Hiiro"}) -[*..2]->(m)
RETURN *;

查询两个节点之间的所有路径,指定深度最大为 4 4 4

MATCH path = (n:DOG) -[*..4]->(m:MOUSE)
WHERE n.name = "LYS" AND m.name = "ChenRay"
RETURN path;

查询两个节点之间的最短路径,指定深度最大为 6 6 6

MATCH path = shortestPath((n:DOG) -[*..6]->(m:MOUSE))
WHERE n.name = "LYS" AND m.name = "ChenRay"
RETURN path;

分页查询


使用 SKIPLIMIT 子句来指定要跳过的结果数量和要返回的结果数量:

MATCH (nodes)
RETURN nodes
SKIP <skipCount>
LIMIT <pageSize>;

其中:

  • (nodes) 是节点模式或关系模式,用于指定要返回的节点或关系。
  • SKIP <skipCount> 是用于指定要跳过的结果数量的子句。<skipCount> 是要跳过的结果数量。
  • LIMIT <pageSize> 是用于指定要返回的结果数量的子句。<pageSize> 是要返回的结果数量。

通过适当设置 <skipCount><pageSize> 的值,可以实现分页查询。

例如分页查询标签为 DOG 的节点信息,按照年龄从小到大排序,每页 2 2 2 条数据:

获取第 1 1 1 页:

MATCH (n:DOG) 
RETURN n 
ORDER BY n.age ASC
SKIP 0 LIMIT 2;

获取第 2 2 2 页:

MATCH (n:DOG) 
RETURN n
ORDER BY n.age ASC
SKIP 2 LIMIT 2;

SET & REMOVE


使用 SETREMOVE 对节点进行标签、属性的更新。

更新节点的属性和标签,例如将标签为 DOG 且年龄小于 60 60 60 节点的标签更改为 BOSS 且年龄增加 10 10 10

MATCH(n:DOG)
WHERE n.age <= 60
SET n:BOSS
SET n.age = n.age + 10
RETURN n;

添加多个标签:

MATCH(n:DOG)
WHERE n.name = "LYS"
SET n:DOG:JOKER:STUDENT
RETURN n;

添加新的属性:

MATCH(n:DOG)
WHERE n.name = "LYS"
SET n.school = "HAUE"
RETURN n;

一次性添加多个属性:

MATCH(n:DOG)
WHERE n.name = "LYS"
SET n += {status: "Learning", money: 0, emo: "🤡"}
RETURN n;

移除某个属性或标签:

MATCH(n:DOG)
WHERE n.name = "LYS"
REMOVE n.emo, n:JOKER
RETURN n;

移除多个属性或标签:

MATCH(n:DOG)
WHERE n.name = "LYS"
REMOVE n.status, n.money, n:BOSS:STUDENT
RETURN n;

DELETE


删除节点:

MATCH(n)
WHERE n.name = "伤心打工人" OR n.name = "黑心老板"
DELETE n;
MATCH(n)
WHERE n.name = "打工人"
DELETE n;

如果删除的节点具有关系,则无法删除,需要先删除对应关系后才能删除节点:

MATCH(n) -[r:WORK_FOR]-> (m)
WHERE n.name = "打工人"
DELETE r, m;

或者添加 DETACH 强制删除该节点及其对应关系:

MATCH (n:DOG {name: "快乐打工人"}) 
DETACH DELETE n;

删除所有节点及其关系:

MATCH(n)
DETACH DELETE n;

索引


Neo4j 中同样支持索引,创建索引,以提高在大型数据集上对节点和关系进行查找和匹配的速度。

Neo4j 索引的底层实现原理主要依赖于两个核心组件:标签扫描器(Label Scanner)和属性索引(Property Index):

  • 标签扫描器(Label Scanner):
    • 使用标签扫描器来快速定位具有特定标签的节点。
    • 标签扫描器维护了一个映射表,其中的每个条目都包含一个标签和指向具有该标签的节点的指针列表。当执行针对特定标签的查询时,标签扫描器可以快速定位到相关节点的位置。
    • 标签扫描器允许在节点创建和删除时进行高效的更新,以保持索引的实时性。
  • 属性索引(Property Index):
    • 属性索引是基于节点和关系属性的值构建的数据结构,用于快速查找具有特定属性值的节点或关系。
    • 使用 B+ 树作为属性索引的底层数据结构。树中的每个节点都包含多个键值对,其中键是属性的值,值是指向具有该属性值的节点或关系的指针。
    • 在执行带有属性条件的查询时,属性索引可以通过在 B+ 树上进行范围搜索或精确查找来快速定位到满足条件的节点或关系。

此外,Neo4j 还提供了全文索引(Full-Text Index)和空间索引(Spatial Index)等特定类型的索引,用于支持全文搜索和地理空间查询。这些特定类型的索引也有其特定的底层实现,这里不再做深究。


创建索引


对节点属性创建索引:

CREATE INDEX ON :Label(property)

这将在具有特定标签(Label)的节点上创建一个属性(property)的索引。

对关系属性创建索引:

CREATE INDEX ON :RELATIONSHIP_TYPE(property)

这将在具有特定关系类型(RELATIONSHIP_TYPE)的关系上创建一个属性(property)的索引。


索引查询


对节点属性使用索引:

MATCH (n:Label)
WHERE n.property = value
RETURN n

这将使用节点属性的索引来查找具有特定属性值的节点。

对关系属性使用索引:

MATCH ()-[r:RELATIONSHIP_TYPE]-()
WHERE r.property = value
RETURN r

这将使用关系属性的索引来查找具有特定属性值的关系。


删除索引


使用 DROP INDEX 删除索引,例如:

DROP INDEX ON :Label(property)

这将删除特定标签(Label)上的属性(property)索引。


官方文档参考


  • Neo4j 4.4 安装
  • Cypher Manual 4.4

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

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

相关文章

学习:原码-反码-补码

文章目录 前提知识原码详解反码补码 二进制负数的运算 前提知识 正数不需要进行原码反码补码一说&#xff0c;正数就是正数&#xff0c;我们原码反码补码是为了针对负数 &#xff08;按道理来说其实根本不存在什么码&#xff0c;只有二进制机器码&#xff0c;不过是为了方便计…

华为云云耀云服务器L实例评测|华为云上安装etcd

文章目录 华为云云耀云服务器L实例评测&#xff5c;华为云上安装etcd一、什么是etcd官方硬件建议 二、华为云主机准备三、etcd安装1. 安装预构建的二进制文件2. 从源代码构建 四、etcd服务注册与发现1. 配置etcd2. 使用systemctl 管理启动etcd服务3. 注册服务4. 发现服务 五、其…

ISE_ChipScope Pro的使用

1.ChipScope Pro Core Inserter 使用流程 在之前以及编译好的流水灯实验上进行学习 ChipScope的使用。 一、新建一个ChipScope 核 点击Next,然后在下一个框中选择 Finish&#xff0c;你就会在项目菜单中看到有XX.cdc核文件。 二、对核文件进行设置 右键“Synthesize – XST” …

最快的包管理器--pnpm创建vue项目完整步骤

1.用npm全局安装pnpm npm install -g pnpm 2.在要创建vue项目的包下进入cmd&#xff0c;输入&#xff1a; pnpm create vue 3.输入项目名字&#xff0c;选择Router,Pinia,ESLint,Prettier之后点确定 4.cd到创建好的项目 &#xff0c;安装依赖 cd .\刚创建好的项目名称\ p…

怎样快速打开github.com

1访问这个网站很慢是因为有DNS污染&#xff0c;被一些别有用心的人搞了鬼了&#xff0c; 2还有一个重要原因是不同的DNS服务器解析的速度不一样。 1 建议设置dns地址为114.114.114.114.我觉得假设一个县城如果有一个DNS服务器的话&#xff0c;这个服务器很可能不会存储…

[linux]服务器挂代理提升下载权重速度

写在前面 这里主要以huggingface下载权重为例&#xff0c;介绍如何在linux中部署代理提升下载速度 实际操作 第一步&#xff1a;服务器安装clash文件 https://github.com/Dreamacro/clash/releases#下载clash链接第二步&#xff1a;使用自己的配置文件 将config.yaml替换掉…

前端项目练习(练习-003-webpack-01)

学习webpack前&#xff0c;首先&#xff0c;创建一个web-003项目&#xff0c;内容和web-002一样。&#xff08;注意将package.json中的name改为web-003&#xff09; 想想&#xff0c;我们开发Java 的时候&#xff0c;Maven帮我们做的主要是编译&#xff0c;打包等等内容。开发前…

Spring Cloud Alibaba Gateway 简单使用

文章目录 Spring Cloud Alibaba Gateway1.Gateway简介2. 流量网关和服务网关的区别3. Spring Cloud Gateway 网关的搭建3.1 Spring Cloud Gateway 配置项的说明3.2 依赖导入3.3 配置文件 Spring Cloud Alibaba Gateway 1.Gateway简介 Spring Cloud Gateway是一个基于Spring F…

计算机竞赛 深度学习乳腺癌分类

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

构建自己的物料解决方案——构建物料库,实现前端设计

01: 数据拦截简化数据获取流程 /** * 响应拦截器&#xff1a; * 服务端返回数据之后&#xff0c;前端 .then 之前被调用 */ service.interceptors.response.use((response) > {const { success, message, data } response.dataif (success) {return data}// TODO&#xff…

法规标准-UN R48标准解读

UN R48是做什么的&#xff1f; UN R48全名为关于安装照明和灯光标志装置的车辆认证的统一规定&#xff0c;主要描述了对各类灯具的布置要求及性能要求&#xff1b;其中涉及自动驾驶功能的仅有6.25章节【后方碰撞预警信号】&#xff0c;因此本文仅对此章节进行解读 功能要求 …

Python中的设计模式 -- 单例

迷途小书童 读完需要 2分钟 速读仅需 1 分钟 当我们谈到单例模式时&#xff0c;可以想象一个非常特殊的餐厅&#xff0c;这个餐厅只有一个桌子&#xff0c;无论多少人来用餐&#xff0c;都只能坐在这个桌子上。这个桌子就是餐厅的单例&#xff0c;它保证了整个餐厅中只有一个桌…

Element登录+注册

Element登录注册 1.1 定义1.3 完成用户注册登录界面搭建1.3.3 下载js依赖1.3.4 创建用户登录注册组件1.3.5 配置路由 二、数据交互2.1 数据导入2.3 安装引用相关模块 2.3.1 安装相关模块2.3.2 引用相关模块2.4 axios之get请求2.5 axios之post请求 四、注册 1.1 定义 ElementUI是…

bash中执行比较的几种方法

bash 脚本中的 test 命令用于检查表达式的有效性&#xff0c;检查命令或表达式为 true 或者 false。此外&#xff0c;它还可以用于检查文件的类型和权限。 如果命令或表达式有效&#xff0c;则 test 命令返回0&#xff0c;否则返回1。 使用 test 命令 test 命令的基本语法如…

腾讯mini项目-【指标监控服务重构】2023-08-29

今日已办 Collector 指标聚合 由于没有找到 Prometheus 官方提供的可以聚合指定时间区间内的聚合函数&#xff0c;所以自己对接Prometheus的api来聚合指定容器的cpu_avg、cpu_99th、mem_avg 实现成功后对接小组成员测试完提供的时间序列和相关容器&#xff0c;将数据记录在表格…

Qt/C++音视频开发56-udp推流和拉流/组播和单播推流

一、前言 之前已经实现了rtsp/rtmp推流&#xff0c;rtsp/rtmp/hls/flv/ws-flv/webrtc等拉流&#xff0c;这种一般都需要依赖一个独立的流媒体服务程序&#xff0c;有没有一种更便捷的方式不需要这种依赖&#xff0c;然后又能实现推拉流呢&#xff0c;当然有的那就是udpp推流&a…

前端项目练习(练习-004-webpack-02)

学习前&#xff0c;首先&#xff0c;创建一个web-004项目&#xff0c;内容和web-003一样。&#xff08;注意将package.json中的name改为web-004&#xff09; 前面的例子&#xff0c;成功将js文件打包到了dist中&#xff0c;但是我们有三个文件&#xff0c;css&#xff0c;js和h…

利用C++开发一个迷你的英文单词录入和测试小程序-增强功能

小玩具基本完成之后&#xff0c;在日常工作中&#xff0c;记录一些单词&#xff0c;然后定时再复习下&#xff0c;还真的有那么一点点用&#xff08;毕竟自己做的小玩具&#xff09;。 在使用过程中&#xff0c;遇到不认识的单词&#xff0c;总去翻译软件翻译&#xff0c;然后…

使用matlab产生二维动态曲线视频文件具体举例

使用matlab产生二维动态曲线视频文件举例 在进行有些函数变化过程时候&#xff0c;需要用到直观的动态显示&#xff0c;本博文将举例说明利用Matlab编程进行二维动态曲线的生成视频文件。 一、问题描述 利用matlab编程实现 y 1 s i n ( t ) , y 2 c o s ( t ) , y 3 s i …

安卓生成公钥和md5签名

安卓公钥和md5证书签名 大家好&#xff0c;最近需要备案app&#xff0c;用到了公钥和md5&#xff0c;MD5签名我倒是知道&#xff0c;然而对于公钥却一下子不知道了&#xff0c; 现在我讲一下我的流程。 首先是md5证书签名的查看&#xff0c; 生成了apk和签名.jks后&…