以下命令用于克隆本教程中使用的应用程序的源代码
git clone --branch v1.2.0 https://github.com/redis-developer/mobile-banking-solutions
账户仪表板是移动银行应用程序中的一个页面,它会立即向用户显示账户重点信息。客户可以点击仪表板上的任何账户以查看实时账户详细信息,例如最新交易、剩余抵押贷款金额、支票和储蓄等。
账户仪表板将客户的财务状况集中在一个地方,方便查看。它降低了客户的财务复杂性,并培养了客户忠诚度。
以下图表是账户仪表板的数据架构示例
Redis Stack支持JSON数据类型,并允许您索引和查询JSON以及更多。因此您的Redis数据不限于简单的键值字符串化数据。
以下命令用于克隆本教程中使用的应用程序的源代码
git clone --branch v1.2.0 https://github.com/redis-developer/mobile-banking-solutions
下载上面的源代码并运行以下命令以启动演示应用程序
docker compose up -d
在docker启动并运行后,在浏览器中打开https://localhost:8080/ URL以查看应用程序
此应用程序利用Redis核心数据结构、JSON、TimeSeries、搜索和查询功能。播种的数据稍后用于显示可搜索的交易概述(具有实时更新),以及个人财务管理概述(具有实时余额和最大支出者更新)。
在应用程序启动时(在app/server.js
中),会安排一个cron以定期创建随机银行交易并将这些交易播种到Redis中。
//cron job to trigger createBankTransaction() at regular intervals
cron.schedule('*/10 * * * * *', async () => {
const userName = process.env.REDIS_USERNAME;
createBankTransaction(userName);
//...
});
balanceAfter
值记录在TimeSeries中,其键为balance_ts
,用于每次交易。bigspenders
中的关联成员fromAccountName
会增加交易金额。请注意,此金额可能是正数或负数。let balance = 100000.0;
const BALANCE_TS = 'balance_ts';
const SORTED_SET_KEY = 'bigspenders';
export const createBankTransaction = async () => {
//to create random bank transaction
let vendorsList = source.source; //app/transactions/transaction_sources.js
const random = Math.floor(Math.random() * 9999999999);
const vendor = vendorsList[random % vendorsList.length]; //random vendor from the list
const amount = createTransactionAmount(vendor.fromAccountName, random);
const transaction = {
id: random * random,
fromAccount: Math.floor((random / 2) * 3).toString(),
fromAccountName: vendor.fromAccountName,
toAccount: '1580783161',
toAccountName: 'bob',
amount: amount,
description: vendor.description,
transactionDate: new Date(),
transactionType: vendor.type,
balanceAfter: balance,
};
//redis json feature
const bankTransaction = await bankTransactionRepository.save(transaction);
console.log('Created bankTransaction!');
// ...
};
const createTransactionAmount = (vendor, random) => {
let amount = createAmount(); //random amount
balance += amount;
balance = parseFloat(balance.toFixed(2));
//redis time series feature
redis.ts.add(BALANCE_TS, '*', balance, { DUPLICATE_POLICY: 'first' });
//redis sorted set as secondary index
redis.zIncrBy(SORTED_SET_KEY, amount * -1, vendor);
return amount;
};
使用RedisInsight查看bankTransaction数据示例
下载RedisInsight以查看您的Redis数据或在工作台中使用原始Redis命令进行操作。
仪表板小部件
API端点
端点 | /transaction/balance |
代码位置 | /routers/transaction-router.js |
参数 | 无 |
返回值 | [{x: timestamp, y: value}, ...] |
余额端点利用时间序列,它返回时间序列对象balance_ts
中的所有值范围。生成的范围将转换为一个对象数组,每个对象包含一个x
属性(包含时间戳)和一个y
属性(包含关联的值)。此端点为时间序列图表提供坐标,以绘制随时间推移的余额的可视化图表。
const BALANCE_TS = 'balance_ts';
/* fetch transactions up to sometime ago */
transactionRouter.get('/balance', async (req, res) => {
//time series range
const balance = await redis.ts.range(
BALANCE_TS,
Date.now() - 1000 * 60 * 5, //from
Date.now(), //to
);
let balancePayload = balance.map((entry) => {
return {
x: entry.timestamp,
y: entry.value,
};
});
res.send(balancePayload);
});
仪表板小部件
API端点
端点 | /transaction//biggestspenders |
代码位置 | /routers/transaction-router.js |
参数 | 无 |
返回值 | {labels:[...], series:[...] } |
最大的支出者端点利用 排序集 作为二级索引,它检索排序集 bigspenders
中所有得分大于零的成员。返回前五个或更少的成员,以便为 UI 饼图提供数据。标签数组包含最大支出者的名称,系列数组包含与每个成员名称关联的数值。
const SORTED_SET_KEY = 'bigspenders';
/* fetch top 5 biggest spenders */
transactionRouter.get('/biggestspenders', async (req, res) => {
const range = await redis.zRangeByScoreWithScores(
SORTED_SET_KEY,
0,
Infinity,
);
let series = [];
let labels = [];
range.slice(0, 5).forEach((spender) => {
series.push(parseFloat(spender.score.toFixed(2)));
labels.push(spender.value);
});
res.send({ series, labels });
});
仪表板小部件
API端点
端点 | /transaction/search |
代码位置 | /routers/transaction-router.js |
查询参数 | term |
返回值 | 与 term 匹配的结果数组 |
搜索端点利用 搜索和查询,它从 UI 接收 term
查询参数。 Redis om Node 对字段 description
, fromAccountName
,和 accountType
的查询将触发并返回结果。
transactionRouter.get('/search', async (req, res) => {
const term = req.query.term;
let results;
if (term.length >= 3) {
results = await bankRepo
.search()
.where('description')
.matches(term)
.or('fromAccountName')
.matches(term)
.or('transactionType')
.equals(term)
.return.all({ pageSize: 1000 });
}
res.send(results);
});
仪表板小部件
API端点
端点 | /transaction/transactions |
代码位置 | /routers/transaction-router.js |
参数 | 无 |
返回值 | 结果数组 |
即使是交易端点也利用 搜索和查询。 Redis om Node 查询将触发并返回十个最新的交易。
/* return ten most recent transactions */
transactionRouter.get('/transactions', async (req, res) => {
const transactions = await bankRepo
.search()
.sortBy('transactionDate', 'DESC')
.return.all({ pageSize: 10 });
res.send(transactions.slice(0, 10));
});
希望本教程能帮助您了解如何在移动银行中使用 Redis 来构建账户概览,特别是针对移动银行的场景。有关此主题的更多资源,请查看以下链接。