您当前的位置:首页 > 电脑百科 > 数据库 > 百科

LowDB 轻量级 JSON 本地数据库

时间:2022-07-04 12:26:23  来源:效能哥  作者:

作为轻量级的本地存储方式,对于构建不依赖服务器的小型项目,用LowDB存储和管理数据是十分理想的选择。在Nodejs, Electron and browser等一些小型项目中经常能看到LowDB的身影。

https://github.com/typicode/lowdb

1. 使用方式

npm install lowdb

或者:

yarn add lowdb

const low = require('lowdb');

const FileSync = require('lowdb/adapters/FileSync'); // 有多种适配器可选择

 

const adapter = new FileSync('db.json'); // 申明一个适配器

const db = low(adapter);

 

db.defaults({posts: [], user: {}, count: 0})

.write();

 

db.get('posts')

.push({id: 1, title: 'lowdb is awesome'})

.write()

 

db.set('user.name', 'typicode')

.write()

 

db.update('count', n => n + 1)

.write()

运行程序会在项目中添加db.json文件,里面存储了添加的数据:

{

"posts": [

{

"id": 1,

"title": "lowdb is awesome"

}

],

"user": {

"name": "typicode"

},

"count": 1

}

lowdb是基于lodash构建的,所以可以使用任何lodash强大的函数,比如: _.get() 和 _.find(),并且可以串联地使用:

db.get('users')

.find({sex: 'male'})

.value()

2. API

函数 功能

low(adapter) 返回一个具有特定属性和功能的 lodash chain

db.[...].write() / .value() 写 / 读数据

db.getState() / .setState() 获取 / 设置数据库的状态

db._ 数据库lodash的实例,可以利用这个添加自己的函数或者第三方的mixins,比如lodash-id

db._.mixin({

second: function(array) {

return array[1]

}

})

db.get('posts')

.second()

.value()

3. Adapters API

针对lowdb自带的适配器:FileSync、FileAsync 和 LocalBrowser,有以下可选参数:

defaultValue: 文件不存在时的默认值;

serialize/deserialize: 写之前和读之后的操作。

const adapter = new FilSync('db.json',{

serialize: (data) => encrypt(JSON.stringify(data)),

deserialize: (data) => JSON.parse(decrypt(data))

})

4. 查询

可以直接使用lodash的函数进行查询。需要注意的是有些操作可能会导致原数据被修改,为了避免这种误操作,需要使用 .cloneDeep(),操作都是惰性的,只有调用 .value()或 .write()后才会正式执行。

检查users是是否存在

db.has('users')

.value()

设置users

db.set('users', [])

.write()

排序、选择

db.get('users')

.filter({sex: 'male'})

.sortBy('age')

.take(5)

.value()

获取特定字段

db.get('users')

.map('name')

.value()

获取数量

db.get('users')

.size()

.value()

获取特定信息

db.get('users[0].name')

.value()

更新信息

db.get('users')

.find({name: 'Tom'})

.assign({name: 'Tim'})

.write()

删除信息

db.get('users')

.remove({name: 'Time'})

.write()

移除属性

db.unset('users.name)

.write()

深拷贝

db.get('users')

.cloneDeep()

.value()

5. 使用id索引

可以使用 shortid 和 lodash-id 为数据库中的每一条记录创建唯一的id索引,然后通过id检索操作记录:

const shortid = require('shortid')

 

const postId = db

.get('posts')

.push({ id: shortid.generate(), title: 'low!' })

.write()

.id

 

const post = db

.get('posts')

.find({ id: postId })

.value()

const lodashId = require('lodash-id')

const FileSync = require('lowdb/adapters/FileSync')

 

const adapter = new FileSync('db.json')

const db = low(adapter)

 

db._.mixin(lodashId)

 

// We need to set some default values, if the collection does not exist yet

// We also can store our collection

const collection = db

.defaults({ posts: [] })

.get('posts')

 

// Insert a new post...

const newPost = collection

.insert({ title: 'low!' })

.write()

 

// ...and retrieve it using its id

const post = collection

.getById(newPost.id)

.value()

6. 自定义Adapter

low( ) 函数接受自定义的Adapter

class MyStorage {

constructor() {

// ...

}

 

read() {

// Should return data (object or array) or a Promise

}

 

write(data) {

// Should return nothing or a Promise

}

}

 

const adapter = new MyStorage(args)

const db = low(adapter);

 

 

==============================================

 

英文官网介绍,更加简洁

 

Install


npm install lowdb

Usage

Lowdb 3 is a pure ESM package. If you're having trouble importing it in your project, please read this.

import { join, dirname } from 'path'
import { Low, JSONFile } from 'lowdb'
import { fileURLToPath } from 'url'

const __dirname = dirname(fileURLToPath(import.meta.url));

// Use JSON file for storage
const file = join(__dirname, 'db.json')
const adapter = new JSONFile(file)
const db = new Low(adapter)

// Read data from JSON file, this will set db.data content
await db.read()

// If file.json doesn't exist, db.data will be null
// Set default data
// db.data = db.data || { posts: [] } // Node < v15.x
db.data ||= { posts: [] }             // Node >= 15.x

// Create and query items using plain JS
db.data.posts.push('hello world')
const firstPost = db.data.posts[0]

// Alternatively, you can also use this syntax if you prefer
const { posts } = db.data
posts.push('hello world')

// Finally write db.data content to file
await db.write()
// db.json
{
  "posts": [ "hello world" ]
}

TypeScript

You can use TypeScript to type check your data.

type Data = {
  words: string[]
}

const adapter = new JSONFile<Data>('db.json')
const db = new Low(adapter)

db.data
  .words
  .push('foo') // ✅

db.data
  .words
  .push(1) // ❌

Lodash

You can also add lodash or other utility libraries to improve lowdb.

import lodash from 'lodash'

type Post = {
  id: number;
  title: string;
}

type Data = {
  posts: Post[]
}

// Extend Low class with a new `chain` field
class LowWithLodash<T> extends Low<T> {
  chain: lodash.ExpChain<this['data']> = lodash.chain(this).get('data')
}

const adapter = new JSONFile<Data>('db.json')
const db = new LowWithLodash(adapter)
await db.read()

// Instead of db.data use db.chain to access lodash API
const post = db.chain
  .get('posts')
  .find({ id: 1 })
  .value() // Important: value() must be called to execute chain

More examples

For CLI, server and browser usage, see examples/ directory.

API

Classes

Lowdb has two classes (for asynchronous and synchronous adapters).

new Low(adapter)

import { Low, JSONFile } from 'lowdb'

const db = new Low(new JSONFile('file.json'))
await db.read()
await db.write()

new LowSync(adapterSync)

import { LowSync, JSONFileSync } from 'lowdb'

const db = new LowSync(new JSONFileSync('file.json'))
db.read()
db.write()

Methods

db.read()

Calls adapter.read() and sets db.data.

Note: JSONFile and JSONFileSync adapters will set db.data to null if file doesn't exist.

db.data // === null
db.read()
db.data // !== null

db.write()

Calls adapter.write(db.data).

db.data = { posts: [] }
db.write() // file.json will be { posts: [] }
db.data = {}
db.write() // file.json will be {}

Properties

db.data

Holds your db content. If you're using the adapters coming with lowdb, it can be any type supported by JSON.stringify.

For example:

db.data = 'string'
db.data = [1, 2, 3]
db.data = { key: 'value' }

Adapters

Lowdb adapters

JSONFileJSONFileSync

Adapters for reading and writing JSON files.

new Low(new JSONFile(filename))
new LowSync(new JSONFileSync(filename))

MemoryMemorySync

In-memory adapters. Useful for speeding up unit tests.

new Low(new Memory())
new LowSync(new MemorySync())

LocalStorage

Synchronous adapter for window.localStorage.

new LowSync(new LocalStorage(name))

TextFileTextFileSync

Adapters for reading and writing text. Useful for creating custom adapters.

Third-party adapters

If you've published an adapter for lowdb, feel free to create a PR to add it here.

Writing your own adapter

You may want to create an adapter to write db.data to YAML, XML, encrypt data, a remote storage, ...

An adapter is a simple class that just needs to expose two methods:

class AsyncAdapter {
  read() { /* ... */ } // should return Promise<data>
  write(data) { /* ... */ } // should return Promise<void>
}

class SyncAdapter {
  read() { /* ... */ } // should return data
  write(data) { /* ... */ } // should return nothing
}

For example, let's say you have some async storage and want to create an adapter for it:

import { api } from './AsyncStorage'

class CustomAsyncAdapter {
  // Optional: your adapter can take arguments
  constructor(args) {
    // ...
  }

  async read() {
    const data = await api.read()
    return data
  }

  async write(data) {
    await api.write(data)
  }
}

const adapter = new CustomAsyncAdapter()
const db = new Low(adapter)

See src/adapters/ for more examples.

Custom serialization

To create an adapter for another format than JSON, you can use TextFile or TextFileSync.

For example:

import { Adapter, Low, TextFile } from 'lowdb'
import YAML from 'yaml'

class YAMLFile {
  constructor(filename) {
    this.adapter = new TextFile(filename)
  }

  async read() {
    const data = await this.adapter.read()
    if (data === null) {
      return null
    } else {
      return YAML.parse(data)
    }
  }

  write(obj) {
    return this.adapter.write(YAML.stringify(obj))
  }
}

const adapter = new YAMLFile('file.yaml')
const db = new Low(adapter)

Limits

Lowdb doesn't support Node's cluster module.

If you have large JAVAScript objects (~10-100MB) you may hit some performance issues. This is because whenever you call db.write, the whole db.data is serialized using JSON.stringify and written to storage.

Depending on your use case, this can be fine or not. It can be mitigated by doing batch operations and calling db.write only when you need it.

If you plan to scale, it's highly recommended to use databases like PostgreSQL or MongoDB instead.



Tags:数据库   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
SQLite 是一个被大家低估的数据库,因为有很多人认为它是一个不适合生产环境使用的玩具数据库。但事实上,SQLite 是一个非常可靠的数据库,它可以处理 TB 级的数据,虽然它没有网络...【详细内容】
2022-10-11  Tags: 数据库  点击:(10)  评论:(0)  加入收藏
读写数据库大多数情况下,海量的数据是使用数据库进行数据库进行存储的,这主要是依赖于数据库的数据结构化、数据共享性、独立性等特点。因此,在实际生产环境中,绝大多数的数据都...【详细内容】
2022-09-23  Tags: 数据库  点击:(20)  评论:(0)  加入收藏
有时候部署服务器正式版与测试版数据库的时候总会有人忘记某些字段同步更新的问题不管是字段类型 或是字段名称. 然后等待着的就是一堆的错误日志.所以一直想找一款可以查找...【详细内容】
2022-09-12  Tags: 数据库  点击:(42)  评论:(0)  加入收藏
步骤一:设置sql server数据库1.以新建一个新用户名test作为远程连接登录名。在本地登录sql server数据库,安全性->右键用户名 2.点击根目录右键,选择属性 选择安全性 选...【详细内容】
2022-09-11  Tags: 数据库  点击:(50)  评论:(0)  加入收藏
数据库更改是开发过程中一个棘手的部分。我们能否像对待代码一样对待数据库,将其作为 CI/CD 周期的一部分?数据库更改是应用程序开发过程中一个棘手的部分:它通常涉及来自不同...【详细内容】
2022-09-03  Tags: 数据库  点击:(64)  评论:(0)  加入收藏
在日常开发中,经常会需要进行数据库操作,如执行一些 SQL 查询、或者执行一些 SQL 命令等,如果每次执行操作都按照 Delphi 数据库操作的步骤一步一步地组织语句去执行的话,又显得...【详细内容】
2022-09-01  Tags: 数据库  点击:(70)  评论:(0)  加入收藏
尊敬的客户:非常荣幸地通知您,华为认证HCIE-GaussDB-OLTP V1.0(中文版)预计将于2022年09月30日正式对外发布。为了帮助您做好学习、培训和考试计划,现进行预发布通知,请您关注。一...【详细内容】
2022-08-30  Tags: 数据库  点击:(178)  评论:(0)  加入收藏
开发中经常说到数据入库,我们在实现时需要知道使用何种技术,连接哪个数据库,连接数据库的账号和密码等等。今天要跟大家分享的是spring web项目中使用mybatis连接到postgresql...【详细内容】
2022-08-29  Tags: 数据库  点击:(54)  评论:(0)  加入收藏
摘要:区别于PostgreSQL和Oracle,MariaDB采取的是一种现代的云原生的方法,在低成本、耐用的云存储上管理几乎无限量的地理空间数据,并提供基于OGC(开放地理空间信息联盟)标准的REST...【详细内容】
2022-08-29  Tags: 数据库  点击:(41)  评论:(0)  加入收藏
你在刷抖音的时候,有没有发现,抖音从来不会给你推送相同内容的视频?你可能会想,这有啥难的,给每个人都存一个记录,以后推送的时候避开就好了呀。nononono!可没有这么简单啊!海量用户...【详细内容】
2022-08-22  Tags: 数据库  点击:(68)  评论:(0)  加入收藏
▌简易百科推荐
0 HBase简介HBase是一个构建在HDFS之上,用于海量数据存储分布式列存储系统。 表的每行都是按照RowKey的字典序排序存储 表的数据是按照RowKey区间进行分割存储成多个region所...【详细内容】
2022-10-15  存储矩阵  今日头条  Tags:HBase   点击:(3)  评论:(0)  加入收藏
SQLite 是一个被大家低估的数据库,因为有很多人认为它是一个不适合生产环境使用的玩具数据库。但事实上,SQLite 是一个非常可靠的数据库,它可以处理 TB 级的数据,虽然它没有网络...【详细内容】
2022-10-11  爆笑欢乐     Tags:SQLite   点击:(10)  评论:(0)  加入收藏
概述Apache Calcite的前身是optiq,是Hive中做CBO(Cost Based Optimization, 基于成本的优化)的一个模块。2014年5月从Hive项目中独立出来,成为Apache社区的孵化项目,同年9月正...【详细内容】
2022-10-05  yuanyeex  今日头条  Tags:Apache Calcite   点击:(23)  评论:(0)  加入收藏
1. 概览在过去的3个月中,我们发布上线了冷热数据分离存储等功能。今天很高兴和大家交流PolarDB-X最新的内核版本5.4.15。在最新版本中,提供诸多新的功能:存储过程,读写分离优...【详细内容】
2022-09-27  阿里云数据库  今日头条  Tags:MySQL   点击:(24)  评论:(0)  加入收藏
摘要:输入一条语句,返回一个结果,却不知道这条语句在 MySQL 内部的执行过程。 本文分享自华为云社区《一条查询SQL是如何执行的-云社区-华为云》,作者: 共饮一杯无 。执行如下SQL...【详细内容】
2022-09-26  互联网资讯看板     Tags:SQL语句   点击:(30)  评论:(0)  加入收藏
现在数据库里有一张由销售员姓名、销售产品、销售额三个字段构成的销售业绩表。想知道空调和电视销售额都在前 10 名的销售员名单。大家第一反应应该是写一段SQL。对专业的...【详细内容】
2022-09-26  播鹰科技     Tags:SQL   点击:(13)  评论:(0)  加入收藏
基于数据库的实现方案 UUID 获取系统当前时间 snowflake 算法问: 分库分表之后,id 主键如何处理?面试官心理分析其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因...【详细内容】
2022-09-23  男神是孟德大人啊  今日头条  Tags:分库分表   点击:(19)  评论:(0)  加入收藏
读写数据库大多数情况下,海量的数据是使用数据库进行数据库进行存储的,这主要是依赖于数据库的数据结构化、数据共享性、独立性等特点。因此,在实际生产环境中,绝大多数的数据都...【详细内容】
2022-09-23  KJ丶JK    Tags:数据库   点击:(20)  评论:(0)  加入收藏
在前面一篇文章中提到过对于业务主表读写缓慢的解决方案:冷热分离,有不了解的请看:业务主表读写缓慢如何优化?冷热分离固然是一个性价比高的解决方案,但也并不是银弹,仍然有诸多限...【详细内容】
2022-09-19  不才陈某  微信公众号  Tags:查询分离   点击:(25)  评论:(0)  加入收藏
概述随着数据库中数据量日益增多,不得进行分库分表,在分库后将数据分布到不同的数据库实例(甚至物理机器)上,以达到降低数据量,提高系统的处理能力,但是这种架构也带来其他问题,比如...【详细内容】
2022-09-10  职场报料汇  网易号  Tags:分库分表   点击:(72)  评论:(0)  加入收藏
站内最新
站内热门
站内头条