IndexedDB的包装器JsStore - 基础语法

        JsStore是IndexedDB的包装器。它提供了简单的SQL像api,这是容易学习和使用的。   

         IndexedDb查询可以在web worker内部执行,JsStore通过提供一个单独的worker文件来保持这种功能。

        因此查询可以以两种方式执行——在web worker内部或在web worker之外。建议使用web worker,因为它在后台线程中运行脚本。

       在之前几篇我们使用的Indexed是相关函数api,实现某些功能难度较大,但使用JsStore之后就会比较方便了。

        这里还是以Vue技术框架为例,带领大家使用JsStore来实现增删改查功能。

一、安装

        安装JsStore的方法多种多样,我们可以从github下载脚本,也可以通过npm进行安装。

1.1 安装最新版本

npm install jsstore

1.2 安装指定版本

npm install jsstore@3.0.0

二、创建数据库

2.1 创建连接文件

        jsstore -它包含所有的api和你的代码与它的交互,jsstore worker 它包含了所有的逻辑,可以用来创建有worker或没有worker的连接。

           在src目录下创建src/db/index.js文件,来实例connection连接对象,代码如下:

import { Connection } from "jsstore";
import workerInjector from "jsstore/dist/worker_injector";

let connection = new Connection();
connection.addPlugin(workerInjector);

export default connection;

2.2 列表参数

        jsstore中的Column是一个对象,其中列名是键,列选项是值。

        列的选项:

名称类型描述
primaryKeyboolean将此列声明为主键(可选)
notNullboolean确保该列值不应为空(可选)
dataTypeJsStore.DATA_TYPE此列的数据类型(可选)
autoIncrementboolean自动增加值(可选)
uniqueboolean该列将具有惟一值(可选)
defaultany在未指定列时为列提供默认值(可选)
multiEntryboolean提供对数组值内部搜索的支持(可选)
enableSearchboolean打开/关闭该列的搜索(可选)
keyPathstring[]允许你使用多个索引//可选

2.3 数据类型

        数据类型DATA_TYPE是公共的,所以可以使用它来定义字段的类型。

类型名称对应类型描述
Stringstring字符串
Numbernumber数值
DateTimedate_time值应该是date对象,即value = new date ()
Objectobject对象
Arrayarray数组
Booleanboolean布尔值

2.4 创建数据表

        在src目录下创建src/db/service.js文件,用来定义表结构和数据类型,并定义initJsStore()初始化数据库函数,代码如下:

import connection from './index.js';
import { DATA_TYPE } from "jsstore";

const getDatabase = () => {
	//用户表
	const UserTable = {
		name: "Users",
		columns: {
			id: { primaryKey: true, autoIncrement: true },
			username: { notNull: true, dataType: DATA_TYPE.String },
			password: { notNull: true, dataType: DATA_TYPE.String },
			role: { notNull: true, dataType: DATA_TYPE.Number },
			token: { notNull: false, dataType: DATA_TYPE.String },
			createtime: { notNull: true, dataType: DATA_TYPE.DateTime },
			updatetime: { notNull: true, dataType: DATA_TYPE.DateTime },
		}
	}
	
	//岗位管理
	const PostTable = {
		name: "Post",
		columns: {
			id: { primaryKey: true, autoIncrement: true },
			name: { notNull: true, dataType: DATA_TYPE.String },
			remark: { notNull: false, dataType: DATA_TYPE.String },
			createtime: { notNull: true, dataType: DATA_TYPE.DateTime },
			updatetime: { notNull: true, dataType: DATA_TYPE.DateTime },
		}
	}
	
	const dataBase = {
			name: "test_System",
			tables: [UserTable, PostTable],
			version: 1
	};
	return dataBase;
}

export const initJsStore = async () => {
	const dataBase = await getDatabase();
	return await connection.initDb(dataBase);
}

        在service.js创建好后,在App.vue中初始化数据库,代码如下:

<script>
  import { mapGetters } from 'vuex'
  import { initJsStore } from '@/db/service.js'
  export default {
    name: 'App',
    data(){
      return {
          users: new UserService()
      }
    },
    created() {
      initJsStore();
    }
  }
</script>

三、封装实体模型

        通过定义实体模型,class是构造函数的语法糖,理解如何使用原型对象实现类和类继承。通过类来创建对象,使得开发不必写重复的代码,以达到代码复用的目的。

3.1 构建类

        引入connection实例来连接数据库,通过JsStore的api函数实现用户表的增删改查。引入md5实现用户密码的加密处理,md5大家可以从网上下载js文件引入,也可以通过npm进行安装。

import { connection } from "@/db/index.js";
import { hex_md5 } from '@/utils/md5'

export class UserService {
  constructor(){
    this.tableName = "Users";
  }
}

3.2 查询数据

        select api用于从数据库中选择数据,相关参数选项如下:

名称 类型描述
limitNumberLimit用于指定要返回的记录数量
skipNumberSkip用于指定要跳过的记录数
orderObjectOrder By用于根据任何列按升序或降序对数据进行排序。
    - byString排序列名
    - typeString排序类型- asc/desc,默认为asc
    - idbSortingBoolean是按indexeddb排序还是按jsstore排序,默认- true
aggregateObject聚合函数对多个值执行计算并返回单个值。
    - countNumber返回指定列的行数。
    - sumNumber返回数值列的总和。
    - avgNumber返回数值列的平均值。
    - maxNumber返回指定列的最大值。
    - minNumber返回指定列的最小值。
groupByStringGroup By用于按一个或多个列对结果集进行分组。您还可以将Aggregate函数与group by一起使用,类似于在SQL中使用的方法。
distinctBooleanDistinct用于返回唯一的结果集。Distinct过滤除主列以外的所有列的结果,因为主列将使结果始终是唯一的。
caseObject

Case是选择查询中的一个选项,用于根据某些条件更改存储值。它类似于多个if else语句。因此,一旦条件为真,它就会停止并返回值。

可以使用其他类似于上面使用的'='的运算符符号- '>','>=,'<','<=','!= '

joinObjectJsStore支持两种连接——内连接(默认)和左连接。
    - withstring要连接的表的名称
    - onstring连接条件eg - table1。Property = table2.property
    - asObject重命名一些列名,以避免与其他表的列匹配
    - whereObject过滤
    - orderObject对于数据排序——但与没有连接的查询不同,这里的排序略有不同。需要以[tablename]的形式提供查询和表名
    - groupByObject进行分组
    - aggregateObject数据聚合
flattenBoolean扁平化是选择查询中的一个选项,它将数组数据扁平化为基本数据。
storeArrayStore是select API中的一个选项,允许从变量中查询现有数据。所有查询选项,如排序,在哪里,分组,聚合等都可以执行。

        如查询用户列表,或指定ID查询用户信息,代码如下:

import connection from "@/db/index.js";
import { hex_md5 } from '@/utils/md5'

export class UserService {
  constructor(){
    this.tableName = "Users";
  }

  //获取用户列表信息
  getUsers(){
    return connection.select({
      from: this.tableName
    });
  }

  /**
   * 通过ID获取用户信息
   * @param {Object} id
   */
  getUserById(id){
    return connection.select({
      from: this.tableName,
      where: { id }
    });
  }
}

        获取列表数据,调用getUsers()函数,代码如下:

let users = new UserService();

let data = await users.getUsers();

3.3 条件查询

        Where可以用来过滤与Sql Where子句相同的记录,相关参数选项如下:

名称类型描述
likeObject

Like与Where一起使用,用于搜索列中的指定模式。目前我们只支持'%'字符。JsStore支持的一些样例

like “a%”:查找以“a”开头的任何值。

like “%a”:查找以“a”结尾的任何值。

like '%a%':查找在任何位置包含"a"的任何值。

inArrayIn允许您在Where查询中指定多个值。它是多重或查询的简写。
regexRegexRegex与Where一起用于在列值中搜索指定的模式。有关正则表达式的更多信息,请访问mozilla正则表达式指南
orObject或可以与where一起使用以过滤记录,以包括任何条件为真的记录。
operators

JsStore支持以下操作符:—

" > ":查找大于提供值的值。

" < ":查找小于所提供值的值。

" >= ":查找大于或等于提供值的值。

" <= ":查找值小于或等于提供的值。

" - ":在两个提供值之间查找值。阅读文档以获得更多信息。

" != ":查找值不等于所提供的值。

between“-”符号用于在两个值之间选择结果。值应该仅为数字。

        如关键词模糊查询,搜索用户名称,增加getUserByName()函数,代码如下:

/**
 * 模糊查询用户名
 * @param {Object} name
 */
getUserByName(name){
	return connection.select({
		from: this.tableName,
		where: {
			username: {
				like: `%${name}%`
			}
		}
	});
}

        如查询创建时间范围值,在getUserByName()函数中where增加between,代码如下:

/**
 * 模糊查询用户名,并指定创建时间范围
 * @param {Object} param
 */
getUserByNames(param){
	let nameParam = {};
	//模糊查询
	if(param['name']){
		nameParam['like'] = `%${param.name}%`;
	}
	//时间范围
	if(Array.isArray(param['timeArray'])&&param['timeArray'].length==2){
		nameParam['-'] = param.timeArray;
	}

	return connection.select({
		from: this.tableName,
		where: {
			username: nameParam
		}
	});
}


/**
此时select结构如下图:
{
    from: "Users"
    where: {
        username: {
            -: [
                Wed Dec 07 2022 18:30:11 GMT+0800 (中国标准时间) {},
                Thu Dec 08 2022 18:30:11 GMT+0800 (中国标准时间) {}
            ],
            like: "%王三%"
        }
    }
}
*/

        

3.4 插入数据

        插入API用于在表中插入新记录.

名称类型描述
upsertBooleanupsert用于替换现有数据,如果不存在则插入为新记录。upsert是insert api中的一个选项。

        用里使用创建用户为例,并且新增用户的密码需要使用md5进行加密处理,代码如下:

 /**
 * 添加用户数据
 * @param {Object} data
 */
insertUser(data){
	//增加创建和更新时间
	Object.assign(data, {
		createtime: new Date(),
		updatetime: new Date()
	});
	//加密密码
	data['password'] = hex_md5(data.password);
    //插入数据
	return connection.insert({
		into: this.tableName,
		values: [data]
	})
}

3.5 修改用户数据

        update用于修改表中的现有记录。你可以使用where with update来过滤目标记录。

名称类型描述
with operators

一些算术运算符可用于更新数据。

例:比如说,你想在产品表的价格列上加5

mapSetFunction

mapSet提供了一种将更新查询中的设置值转换为存储值的方法。

它是一个使用setValue和storedValue调用的函数。

        例如修改用户信息,代码如下:

/**
 * 修改用户信息
 * @param {Object} id
 * @param {Object} data
 */
editUser(id, data){
	if(data['password']){
		//加密密码
		data['password'] = hex_md5(data.password);
	}
	return connection.update({
		in: this.tableName,
		set: data,
		where: { id }
	});
}

3.6 删除用户数据

        remove API可用于从表中删除记录。其中可以用来过滤目标记录。

        例如删除指定用户信息,代码如下:

/**
 * 删除指定用户信息
 * @param {Object} id
 */
deleteUser(id){
	return connection.remove({
		from: this.tableName,
		where: { id }
	})
}

3.7 记录总数

        count API可用于对表中的记录进行计数。您可以使用where来过滤类似于select的结果。

        例如查询姓名为“王三”用户有多少,代码如下:

/**
 * 统计记录总数
 * @param {Object} name
 */
getCount(name){
	return connection.count({
		from: this.tableName,
		where: { 
			username: {
				like: `%${name}%`
			}
		}
	})
}

3.8 并集查询

        union API结合两个或多个选择查询的结果并删除重复记录。

        例如产品不同价格数据结果的并集查询,代码如下:

var results = await connection.union([
    {
        from: 'Products',
        where: {
            price: {
                '>': 10
            }
        }
    },
    {
        from: 'Products',
        where: {
            price: {
                '>': 50
            }
        }
    }
])

3.9 交集查询

        intersect API将两个或多个select查询的结果组合在一起,只取查询结果之间的公共记录。

        例如产品不同价格数据结果的交集查询,只返回交集数据,代码如下:

var query1=  {
    from: 'Products',
    where: {
        price: {
            '>': 10
        }
    }
};
var query2 = {
    from: 'Products',
    where: {
        price: {
            '>': 50
        }
    }
};
var results = await connection.intersect({
    queries:[query1,query2]    
})

3.10 清空数据表

        清除用于从表中删除所有记录。

注:你也可以使用delete api来清除特定表中的记录,但是clear会很快,不会返回已删除记录的数目,而delete会返回已删除记录的数目。

        代码如下:

await connection.clear(table_name);
console.log('data cleared successfully');
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值