Nodejs 入门8 NeDB 轻量级的Node.js 数据库

news2024/11/19 21:16:30

Nodejs 入门8 NeDB 轻量级的Node.js 数据库

  • 一、简介
    • 1. 什么是 Nedb?
    • 2. 特性和优势
      • 1. 轻量级
      • 2. 简单的API
      • 3. 内存和磁盘存储
  • 二、如何开始使用 Nedb
    • 1. 安装 Nedb
    • 2. 创建数据库实例
      • (1)简单示例
      • (2) options 参数说明
      • (3)更多示例
    • 3. 插入数据
    • 4. 查询数据
    • 5. 查询和分页
    • 6. 投影
    • 7. 查询数量
    • 8. 更新
      • (1)参数说明
        • update
        • options
    • 9. 删除
    • 10. 索引

在这里插入图片描述

一、简介

常用的sqlite轻量级数据库,nodejs在windows环境下安装配置有时候会比较麻烦,很难顺利安装。
Nedb(Node Embedded Database)在一些情况下可以替代sqlite,特别适用于小型项目和快速原型开发。本文将介绍Nedb的基本概念、特性和使用方法,以帮助大家更好地了解和利用这个便捷的工具。

github官网

1. 什么是 Nedb?

Nedb是一个基于Node.js的嵌入式数据库,它在内存中存储数据,同时也支持将数据持久化到磁盘。它的设计灵感来自MongoDB,提供了类似的API和查询语言,而且在运行程序时不用启动独立的数据库服务器。

2. 特性和优势

1. 轻量级

Nedb的主打特性之一就是其轻量级,这使得它成为处理小型项目、原型开发或者快速测试的理想选择。不需要复杂的设置和配置,你可以迅速开始使用它,加速你的开发流程。

2. 简单的API

Nedb的API设计简单易用,与MongoDB的API有很多相似之处。这意味着如果你熟悉MongoDB,你将很容易上手Nedb。基本的CRUD操作都得到了良好的支持,让你能够高效地管理你的数据。

3. 内存和磁盘存储

Nedb支持将数据保存在内存中,也支持将数据持久化到磁盘。这样你可以根据你的项目需求选择合适的存储方式,既可以追求更高的性能,也可以确保数据的持久性。

二、如何开始使用 Nedb

1. 安装 Nedb

使用npm进行安装:

npm install nedb

2. 创建数据库实例

(1)简单示例

const Datastore = require('nedb');
const db = new Datastore({ filename: 'path/to/database.db', autoload: true });

(2) options 参数说明

  • filename(可选):数据持久化的文件路径。如果留空,数据库将被自动视为内存数据库。注意路径不能以~结尾,因为这是NeDB用于执行安全写入的临时文件的标志。
  • inMemoryOnly(可选,默认为false):指定是否为内存数据库。
  • timestampData(可选,默认为false):是否为所有文档添加插入和最后更新的时间戳字段,分别是 createdAt 和 updatedAt。用户指定的值会覆盖自动生成的值,通常用于测试。
  • autoload(可选,默认为false):如果使用此选项,数据库将在创建时自动从数据文件加载(无需调用loadDatabase)。在加载完成之前发出的任何命令都会被缓冲,将在加载完成后执行。
  • onload(可选):如果使用自动加载,这是在loadDatabase之后调用的处理程序。它接受一个错误参数。如果使用自动加载而没有指定此处理程序,如果在加载期间发生错误,将抛出一个错误。
  • afterSerialization(可选):用于在序列化后、写入磁盘之前转换数据的钩子。可以用于在写入数据库到磁盘之前加密数据。此函数以字符串作为参数(NeDB数据文件的一行),并输出转换后的字符串,绝对不能包含\n字符,否则会丢失数据。
  • beforeDeserialization(可选):afterSerialization的反向操作。确保同时包含两者,否则可能导致数据丢失。出于相同的原因,确保两个函数是彼此的反函数。NeDB会检查是否声明了其中一个而没有另一个,并通过对各种长度的随机字符串进行测试,检查它们是否是彼此的反函数来防止数据丢失。此外,如果检测到数据损坏过多,NeDB将拒绝启动,因为这可能意味着您没有在使用序列化钩子之前使用对应的反序列化钩子(请参见下文)。
  • corruptAlertThreshold(可选):介于0和1之间,默认为10%。如果数据文件损坏的百分比超过此阈值,NeDB将拒绝启动。0表示不容忍任何损坏,1表示不关心。
  • compareStrings(可选):函数compareStrings(a, b)比较字符串a和b,返回-1、0或1。如果指定了此函数,它将覆盖默认的字符串比较,后者对于非美国字符(特别是重音字母)不太适用。本机的localCompare在大多数情况下都是正确的选择。
  • nodeWebkitAppName(可选,已弃用):如果从Node Webkit应用程序中使用NeDB,请在此字段中指定其名称(与package.json中使用的名称相同),文件名将相对于Node Webkit用于存储应用程序其他数据(本地存储等)的目录(仅限Linux、OS X和Windows)。现在,您可以在Node Webkit中使用require(‘nw.gui’).App.dataPath获取应用程序数据目录的路径,因此不再建议使用此选项,并将其移除。

(3)更多示例

// 仅内存数据库(无需加载数据库)
const Datastore = require('nedb');
const db = new Datastore();

// 持久数据库,手动加载
const Datastore = require('nedb');
const db = new Datastore({ filename: 'path/to/datafile' });
db.loadDatabase(function (err) {
  // 现在可以执行命令
});

// 持久数据库,自动加载
const Datastore = require('nedb');
const db = new Datastore({ filename: 'path/to/datafile', autoload: true });
// 可以立即发出命令

// Node Webkit应用程序的持久数据库(已弃用)
const Datastore = require('nedb');
const path = require('path');
const db = new Datastore({ filename: path.join(require('nw.gui').App.dataPath, 'something.db') });

如果需要多个数据集合,通常最好为所有集合使用autoload。下面是创建多个数据库实例的示例,通常建议使用autoload为所有集合加载数据库:

const db = {};
db.users = new Datastore('path/to/users.db');
db.robots = new Datastore('path/to/robots.db');

// 异步加载每个数据库
db.users.loadDatabase();
db.robots.loadDatabase();

3. 插入数据

const newData = { name: 'John Doe', age: 25, city: 'New York' };
db.insert(newData, (err, insertedData) => {
  if (err) {
    console.error(err);
  } else {
    console.log('Data inserted:', insertedData);
  }
});

4. 查询数据

下面是官网的一些示例:

// 假设数据库有这些数据
// { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }
// { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }
// { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
// { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }
// { _id: 'id5', completeData: { planets: [ { name: 'Earth', number: 3 }, { name: 'Mars', number: 2 }, { name: 'Pluton', number: 9 } ] } }

// 查找所有太阳系统行星
db.find({ system: 'solar' }, function (err, docs) {
  // docs is an array containing documents Mars, Earth, Jupiter
  // If no document is found, docs is equal to []
});

// 查询找名称里包含ar的,使用正则表达式查询
db.find({ planet: /ar/ }, function (err, docs) {
  // docs contains Mars and Earth
});

// 查找从太阳系继承的
db.find({ system: 'solar', inhabited: true }, function (err, docs) {
  // docs is an array containing document Earth only
});

// 使用点分匹配多级的文档
db.find({ "humans.genders": 2 }, function (err, docs) {
  // docs contains Earth
});

// 使用点分来索引子文档数组
db.find({ "completeData.planets.name": "Mars" }, function (err, docs) {
  // docs contains document 5
});

db.find({ "completeData.planets.name": "Jupiter" }, function (err, docs) {
  // docs is empty
});

db.find({ "completeData.planets.0.name": "Earth" }, function (err, docs) {
  // docs contains document 5
  // If we had tested against "Mars" docs would be empty because we are matching against a specific array element
});


// 深度比较,与点分有所不同
db.find({ humans: { genders: 2 } }, function (err, docs) {
  // docs is empty, because { genders: 2 } is not equal to { genders: 2, eyes: true }
});

// 返回所有数据
db.find({}, function (err, docs) {
});

// The same rules apply when you want to only find one document
db.findOne({ _id: 'id1' }, function (err, doc) {
  // doc is the document Mars
  // If no document is found, doc is null
});

查询操作支持一些运算符,如大于、小于、包含、存在、正则表达式等,示例如下:

// 数值比较
db.find({ "humans.genders": { $gt: 5 } }, function (err, docs) {
  // docs contains Omicron Persei 8, whose humans have more than 5 genders (7).
});

// 字符串比较
db.find({ planet: { $gt: 'Mercury' }}, function (err, docs) {
  // docs contains Omicron Persei 8
})

// in 包含
db.find({ planet: { $in: ['Earth', 'Jupiter'] }}, function (err, docs) {
  // docs contains Earth and Jupiter
});

// 是否存在
db.find({ satellites: { $exists: true } }, function (err, docs) {
  // docs contains only Mars
});

// 联合使用操作符
db.find({ planet: { $regex: /ar/, $nin: ['Jupiter', 'Earth'] } }, function (err, docs) {
  // docs only contains Mars because Earth was excluded from the match by $nin
});

5. 查询和分页

当使用NeDB进行查询(findfindOnecount)而没有指定回调函数时,会返回一个Cursor对象。可以使用sortskiplimit来修改游标,然后使用exec(callback)来执行。

// 假设数据库包含以下4个文档
// doc1 = { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }
// doc2 = { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }
// doc3 = { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
// doc4 = { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }

// 在没有使用查询条件的情况下,返回所有结果(在游标修改器之前)
db.find({}).sort({ planet: 1 }).skip(1).limit(2).exec(function (err, docs) {
  // docs 是 [doc3, doc1]
});

// 可以按照反向顺序排序
db.find({ system: 'solar' }).sort({ planet: -1 }).exec(function (err, docs) {
  // docs 是 [doc1, doc3, doc2]
});

// 可以按照一个字段,然后按照另一个字段排序,以此类推
db.find({}).sort({ firstField: 1, secondField: -1 }) ...   // 你明白这是如何工作的!

这段代码展示了如何使用NeDB进行排序和分页。通过sort方法,可以按照指定字段对结果进行排序,而skiplimit则用于分页。这提供了在NeDB中自定义返回结果顺序和数量的灵活性。

6. 投影

投影是指在查询时指定返回结果中的字段,NeDB提供了投影的功能,类似于MongoDB。投影的语法为:{ a: 1, b: 1 } 表示只返回a和b字段,{ a: 0, b: 0 } 表示省略a和b字段。不同的是,你不能同时使用这两种模式,除非是_id字段,默认情况下总是返回的,但你可以选择省略。投影也可以用于嵌套文档。

// 以上述数据库为例

// 仅保留给定的字段
db.find({ planet: 'Mars' }, { planet: 1, system: 1 }, function (err, docs) {
  // docs 是 [{ planet: 'Mars', system: 'solar', _id: 'id1' }]
});

// 仅保留给定的字段,但省略 _id
db.find({ planet: 'Mars' }, { planet: 1, system: 1, _id: 0 }, function (err, docs) {
  // docs 是 [{ planet: 'Mars', system: 'solar' }]
});

// 仅省略给定的字段,并删除 _id
db.find({ planet: 'Mars' }, { planet: 0, system: 0, _id: 0 }, function (err, docs) {
  // docs 是 [{ inhabited: false, satellites: ['Phobos', 'Deimos'] }]
});

// 失败示例:同时使用两种模式
db.find({ planet: 'Mars' }, { planet: 0, system: 1 }, function (err, docs) {
  // err 是错误消息,docs 是 undefined
});

// 也可以以 Cursor 方式使用,但这种语法与 MongoDB 不兼容
db.find({ planet: 'Mars' }).projection({ planet: 1, system: 1 }).exec(function (err, docs) {
  // docs 是 [{ planet: 'Mars', system: 'solar', _id: 'id1' }]
});

// 对嵌套文档进行投影
db.findOne({ planet: 'Earth' }).projection({ planet: 1, 'humans.genders': 1 }).exec(function (err, doc) {
  // doc 是 { planet: 'Earth', _id: 'id2', humans: { genders: 2 } }
});

这段代码演示了如何在NeDB中使用投影,通过指定查询时返回的字段,可以灵活地控制结果的结构。

7. 查询数量

// Count all planets in the solar system
db.count({ system: 'solar' }, function (err, count) {
  // count equals to 3
});

// Count all documents in the datastore
db.count({}, function (err, count) {
  // count equals to 4
});

8. 更新

db.update(query, update, options, callback)

(1)参数说明

update

指定文档应如何修改。它可以是一个新文档,也可以是一组修饰符,但不能同时使用。

  • 新文档将替换匹配的文档。
  • 修饰符创建它们需要修改的字段,可以应用于子文档。

可用的字段修饰符有

  • $set(更改字段的值)
  • $unset(删除字段)
  • $inc(递增字段的值)
  • $min/$max仅在提供的值小于/大于当前值时更改字段的值。

对于数组,有

  • $push
  • $pop
  • $addToSet
  • $pull
  • $each
  • $slice
options

是一个具有两个可能参数的对象

  • multi(默认为 false)允许如果设置为 true,则修改多个文档
  • upsert(默认为 false)如果要根据更新规则插入新文档,如果查询不匹配任何内容。如果您的更新是一个没有修饰符的简单对象,则它是插入的文档。在其他情况下,查询将递归地去除所有运算符。
  • returnUpdatedDocs(默认为 false,不兼容 MongoDB),如果设置为 true 并且更新不是 upsert,则会返回由查询匹配并更新的文档数组。即使更新实际上没有修改它们,也会返回更新的文档。

一些示例:

// 使用与“查找文档”部分相同的示例集合
// { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false }
// { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true }
// { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
// { _id: 'id4', planet: 'Omicron Persia 8', system: 'futurama', inhabited: true }

// 替换文档
db.update({ planet: 'Jupiter' }, { planet: 'Pluto'}, {}, function (err, numReplaced) {
  // numReplaced = 1
  // 文档 #3 已被替换为 { _id: 'id3', planet: 'Pluto' }
  // 请注意,_id 保持不变,文档已被替换('system' 和 'inhabited' 字段不再存在)
});

// 设置现有字段的值
db.update({ system: 'solar' }, { $set: { system: 'solar system' } }, { multi: true }, function (err, numReplaced) {
  // numReplaced = 3
  // Mars、Earth、Jupiter 上的 'system' 字段现在具有值 'solar system'
});

// 在子文档中使用点符号表示法设置不存在字段的值
db.update({ planet: 'Mars' }, { $set: { "data.satellites": 2, "data.red": true } }, {}, function () {
  // Mars 文档现在是 { _id: 'id1', system: 'solar', inhabited: false
  //                      , data: { satellites: 2, red: true }
  //                      }
  // 请注意,要设置子文档中的字段,您必须使用点符号表示法
  // 使用对象表示法将仅替换顶级字段
  db.update({ planet: 'Mars' }, { $set: { data: { satellites: 3 } } }, {}, function () {
    // Mars 文档现在是 { _id: 'id1', system: 'solar', inhabited: false
    //                      , data: { satellites: 3 }
    //                      }
    // 您失去了“data.red”字段,这可能不是预期的行为
  });
});

// 删除字段
db.update({ planet: 'Mars' }, { $unset: { planet: true } }, {}, function () {
  // 现在 Mars 文档不包含 planet 字段
  // 您当然也可以使用点符号表示法取消嵌套字段
});

// Upsert 文档
db.update({ planet: 'Pluto' }, { planet: 'Pluto', inhabited: false }, { upsert: true }, function (err, numReplaced, upsert) {
  // numReplaced = 1, upsert = { _id: 'id5', planet: 'Pluto', inhabited: false }
  // 已向集合添加了新文档 { _id: 'id5', planet: 'Pluto', inhabited: false }
});

// 如果使用修饰符进行 upsert,那么 upserted 文档是由修饰符修改的查询
// 这比听起来简单:)
db.update({ planet: 'Pluto' }, { $inc: { distance: 38 } }, { upsert: true }, function () {
  // 添加了新文档 { _id: 'id5', planet: 'Pluto', distance: 38 }
});

// 如果

9. 删除

db.remove(query, options, callback) 将根据选项删除与查询匹配的所有文档:

  • query:与用于查找和更新的查询相同
  • options:目前只有一个选项:multi,如果设置为 true,允许删除多个文档。默认为 false
  • callback:可选,签名为:(err, numRemoved)

以下是一些删除文档的示例:

// 使用与“查找文档”部分相同的示例集合
// { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false }
// { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true }
// { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
// { _id: 'id4', planet: 'Omicron Persia 8', system: 'futurama', inhabited: true }

// 从集合中删除一个文档
// 选项设置为 {},因为默认情况下 multi 为 false
db.remove({ _id: 'id2' }, {}, function (err, numRemoved) {
  // numRemoved = 1
});

// 删除多个文档
db.remove({ system: 'solar' }, { multi: true }, function (err, numRemoved) {
  // numRemoved = 3
  // 所有来自太阳系的行星都被移除了
});

// 移除具有“match-all”查询的所有文档
db.remove({}, { multi: true }, function (err, numRemoved) {
});

10. 索引

使用 datastore.ensureIndex(options, cb) 创建索引。

ensureIndex 可以在需要时调用,即使已经插入了一些数据,但最好在应用程序启动时调用。

参数 options 选项包括:

  • fieldName(必需):要创建索引的字段的名称。使用点表示法在嵌套文档中索引字段。
  • unique(可选,默认为 false):强制字段的唯一性。请注意,唯一索引将在尝试为未定义该字段的两个文档创建索引时引发错误。
  • sparse(可选,默认为 false):不要为未定义该字段的文档创建索引。如果希望接受未定义该字段的多个文档,请与 “unique” 选项一起使用。
  • expireAfterSeconds(秒数,可选):如果设置,创建的索引是一个 TTL(生存时间)索引,当系统日期变得大于索引字段上的日期加上 expireAfterSeconds 时,将自动删除文档。未指定索引字段或索引字段不是日期对象的文档将被忽略。
    **注意:_id 会自动带有唯一约束的索引,不需要调用 ensureIndex。 **

删除索引使用 datastore.removeIndex(fieldName, cb)

如果数据存储是持久的,则创建的索引将保存在数据文件中,当第二次加载数据库时,索引会自动创建。

示例:

// 创建索引
db.ensureIndex({ fieldName: 'somefield' }, function (err) {
  // 如果出错,err 不为 null
});

// 使用索引添加唯一约束
db.ensureIndex({ fieldName: 'somefield', unique: true }, function (err) {
});

// 使用稀疏唯一索引
db.ensureIndex({ fieldName: 'somefield', unique: true, sparse: true }, function (err) {
});

// 当唯一约束未满足时的错误消息格式
db.insert({ somefield: 'nedb' }, function (err) {
  // err 为 null
  db.insert({ somefield: 'nedb' }, function (err) {
    // err 为 { errorType: 'uniqueViolated', key: 'name', message: 'Unique constraint violated for key name' }
  });
});

// 移除字段 somefield 上的索引
db.removeIndex('somefield', function (err) {
});

// 使用 expireAfterSeconds 在创建后 1 小时删除文档的示例(db 的 timestampData 选项在此处为 true)
db.ensureIndex({ fieldName: 'createdAt', expireAfterSeconds: 3600 }, function (err) {
});

// 使用该选项设置过期日期
db.ensureIndex({ fieldName: 'expirationDate', expireAfterSeconds: 0 }, function (err) {
  // 现在,所有文档将在系统时间达到其 expirationDate 字段中的日期时过期
});

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

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

相关文章

为什么我说小公司也一定要用K8S

Kubernetes是谷歌以Borg为前身,基于谷歌15年生产环境经验开源的一个项目。Kubernetes致力于提供跨主机集群的自动部署、扩展、高可用以及运行应用程序容器的平台,其遵循主从式架构设计,其组件可以分为工作节点(Node)组…

[力扣 Hot100]Day5 盛最多水的容器

题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明:你不能倾斜容…

vivado ip manager cache

https://china.xilinx.com/video/hardware/configuring-managing-reusable-ip-vivado.html “Core Containers”(核容器):勾选Use Core Containers for IP(为 IP 使用核容器)即可使用核容器功能,该功能支持…

Python操作excel-读取、表格填充颜色区分

1.场景分析 遇到一个需要读取本地excel数据,处理后打入到数据库的场景,使用java比较重,python很好的解决了这类问题 2.重难点 本场景遇到的重难点在于: 需要根据表格内的背景颜色对数据进行筛选 读取非默认Sheet 总是出现Value…

YOLOv8改进 | 细节涨点篇 | UNetv2提出的一种SDI多层次特征融合模块(分割高效涨点)

一、本文介绍 本问给大家带来的改进机制是UNetv2提出的一种多层次特征融合模块(SDI)其是一种用于替换Concat操作的模块,SDI模块的主要思想是通过整合编码器生成的层级特征图来增强图像中的语义信息和细节信息。该方法已在多个公开的医学图像分割数据集上进行了验证,包括皮…

全包了 功能超级强大的linux管理平台1panel部署教程

目录 先看下效果 1.1panel是什么 2.安装教程 2.1下载安装包 2.2解压 2.3安装 3.查看 3.1初始化并登录 3.2容器管理页面,可以启动 重启 创建容器 ​编辑 3.3应用商店 意见安装常用应用 ​编辑 3.4可视化任务管理 3.5网站管理 3.6数据库管理 ​编辑 3…

[计算机提升] 管理设备

4.8 管理设备 通过设备管理器可以对设备进行管理,通常的操作包括:禁用设备、启用设备、安装设备和卸载设备。 4.8.1 禁用、启用、卸载设备 1、打开设备管理器,找到要操作的设备,这里以网络适配器(网卡)示例: 2、右…

electron+vue项目使用serialport报错Cannot read property ‘indexOf‘ of undefined解决办法

描述 使用ElectronVue项目时引入serialport串口后启动时报下面错误 Cannot read property indexOf of undefined解决方法 打开vue.config.js找到pluginOptions -> electronBuilder -> externals添加serialport module.exports {pluginOptions: {electronBuilder: {e…

走迷宫(c语言)

前言: 制作一个迷宫游戏是一个有趣的编程挑战。首先,我们需要设计一个二维数组来表示迷宫的布局,其中每个元素代表迷宫中的一个格子。我们可以使用不同的值来表示空格、墙壁和起点/终点。接下来,我们需生成迷宫。在生成迷宫的过程…

MIT_线性代数笔记:第 26 讲 复矩阵;快速傅里叶变换

目录 复向量 Complex vectors复矩阵 Complex matrices傅里叶变换 Fourier transform快速傅里叶变换 Fast Fourier transform 实矩阵也可能有复特征值,因此无法避免在矩阵运算中碰到复数,本讲学习处理复数矩阵和复向量。 最重要的复矩阵是傅里叶矩阵&…

【备战蓝桥杯】——Day1

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-xKn7nmq36s9pgUXR {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

9 - 数据分片概述|部署MyCat服务

数据分片概述|部署MyCat服务|测试配置 数据分片概述分库分表分割方式水平分割(横向切分)垂直分割(纵向切分) 提供分库分表存储服务软件(中间件)MyCAT软件分片服务器的工作过程 部署M…

基于电源完整性的一些PCB设计建议

基于电源完整性的一些PCB设计建议 1. 尽量减少电源和地通路之间的环路电感,在相邻的层上分配电源和接地面时,使用尽可能薄的电介质; 2. 通过在平面之间使用尽可能高的介电常数来获得平面之间的最低阻抗,与尽可能薄的介电常数设计…

基于springboot的流浪动物救助管理系统

🍅点赞收藏关注 → 私信领取本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅一 、设计说明 1.1研究背景 随着…

Netty-初探

引言 最近开始学习网络编程这一块,特此总结 直接内存为什么比堆内内存要快? JVM在发送堆内数据给远程时,首先会把这部分数据复制到堆外的一块内存空间(防止GC过程中文件引用地址发生变化带来的问题),然后…

陪诊小程序开发|陪诊软件定制|陪诊系统成品功能包含哪些?

陪诊小程序是一种便捷的工具,为用户提供一系列服务和功能,方便患者在就医过程中获得更好的体验和效果。接下来我们将介绍几个主要的陪诊小程序功能。 陪诊小程序开发功能: 一、预约挂号功能。陪诊小程序能够连接用户和医疗机构的系统&#x…

扩散模型微调方法/文献综述

🎀个人主页: https://zhangxiaoshu.blog.csdn.net 📢欢迎大家:关注🔍点赞👍评论📝收藏⭐️,如有错误敬请指正! 💕未来很长,值得我们全力奔赴更美好的生活&…

SMD NTC Thermistor NTC热敏电阻产品基本参数定义

热敏电阻器(Thermistor)是一种电阻值对温度极为灵敏的半导体元件,温度系数可分为Positive Temperature Coefficient 正温度系数热敏电阻又称PTC热敏电阻和Negative Temperature Coefficient 负温度系数热敏电阻又称NTC热敏电阻. NTC热敏电…

基于YOLOv8深度学习的苹果叶片病害智能诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…

外汇天眼:不仅骗钱还骗感情?小心这类骗子盯上你

什么是外汇“杀猪盘”骗局?通俗一点来说就是骗子利用社交平台或者网站,伪造虚假的人设和故事,然后诱导网友进入虚假的外汇平台进行投资交易。随着现代网络科技的发展,各种交友软件可以说是层出不穷,虽然给人们提供了更…