Skip to content

Instantly share code, notes, and snippets.

@Gaubee
Last active May 18, 2018 08:42
Show Gist options
  • Save Gaubee/a0a63216eb7cf9cc38fc9542fc334a5e to your computer and use it in GitHub Desktop.
Save Gaubee/a0a63216eb7cf9cc38fc9542fc334a5e to your computer and use it in GitHub Desktop.
使用数组来链式记录账户的余额
import { MongoClient } from 'mongodb';
const url = 'mongodb://localhost:27017';
const dbName = 'test-set';
import { ConsolePro } from "console-pro";
const console = new ConsolePro();
/**等待n毫秒 */
function sleep(ms: number) {
return new Promise(cb => setTimeout(cb, ms));
}
/**模拟链的高度 */
function getHeight() {
return Math.floor((Date.now() - 1526614267805) / 3e3/* 3s一个高度 */);
}
/**这一轮开始操作的height,小于这个height意味着上一轮 */
const current_round_start_height = getHeight();
console.log("START")
MongoClient.connect(url, async function (err, client) {
try {
console.log("CONNECTED")
const db = client.db(dbName);
const collection = db.collection("t1");
/* 1. 配置索引 */
collection.createIndex({ name: 1 }, {
unique: true
});
collection.createIndex({ "chain.height": -1 }, {
// unique: true
});
/* 2. 生成账户并插入(这里方便测试,只搞两个账户) */
const accounts = Array.from({ length: 2 }, (_, i) => {
return {
name: "test" + i,
chain: [{ balance: 0, height: 0 }] as any[]// 每一次更新都是新增一条记录
}
});
{
const num = await collection.count({});
if (accounts.length > num) {
await collection.insertMany(accounts.slice(num));// 插入账户数据,只插入不存在的
}
}
/* 3. 每个账户随机更新账户 */
const records_list = await Promise.all(accounts.map(async (account) => {
let update_counts = 5;// 更新次数// 随机的更新次数
const records = [] as any[]
for (let i = 0; i < update_counts; i += 1) {
const current_height = getHeight();
const new_balance = (Math.random() * 1000) | 0;
const record = [current_height, new_balance];
const g = console.group(console.flagHead(account.name, false), record);
records.push(record);
const updateRes = await collection.updateOne(
{ name: account.name, "chain.height": current_height },
{ $set: { "chain.$.balance": new_balance, } }
);
/// 找不到可更新的对象,改用插入
console.log('updateRes', updateRes.result);
if (updateRes.result.nModified === 0) {
const insertRes = await collection.updateOne(
{ name: account.name },
// { $addToSet: { chain: { balance: new_balance, height: current_height } } }
// 不使用$addToSet来往后加,使用push来直接插入数组的前面,针对索引需求
{
$push: {
chain: {
$each: [{ balance: new_balance, height: current_height }],
$position: 0
}
}
}
);
console.log('insertRes', insertRes.result);
}
console.groupEnd(g, 'recode update/insert finished.');
await sleep(1000);// 等待随机的时间,再进行下一次账户更新操作
}
return { name: account.name, records };
}));
console.log("UPDATE DONE.");
// console.log(records_list);
/* 4. 根据高度查询 */
{
/// 查询当前的余额,
/* // 使用aggregate管道操作
const cur_me = await collection.aggregate([
{ $match: { name: accounts[0].name } },
{ $project: { name: 1, chainItem: { $arrayElemAt: ["$chain", -1] } } },
{
$project: { name: 1, balance: "$chainItem.balance", lastChangedHeight: "$chainItem.height" }
}]); */
const cur_me = await collection.find(
{
name: accounts[0].name,
},
{ projection: { chain: { $slice: 1 } } }
);
console.flag("cur round account info:", JSON.stringify(await cur_me.toArray()));
const pre_me = await collection.find(
{
name: accounts[0].name,
chain: { $elemMatch: { height: { $lt: current_round_start_height } } }
},
{ projection: { 'chain.$': 1, name: 1 } }
);
console.flag("pre round account info:", JSON.stringify(await pre_me.toArray()));
}
} catch (err) {
console.error(err)
} finally {
process.exit();
}
});
START
CONNECTED
┌ [test0] [ 6211, 556 ]
│ ┌ [test1] [ 6211, 693 ]
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ insertRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ insertRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6211, 532 ]
│ ┌ [test1] [ 6211, 849 ]
│ │ updateRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6212, 889 ]
│ ┌ [test1] [ 6212, 872 ]
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ insertRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ insertRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6212, 918 ]
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test1] [ 6212, 63 ]
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6212, 811 ]
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test1] [ 6212, 800 ]
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
UPDATE DONE.
[cur round account info:] [{"_id":"5afe91c4d4a30e1af449c5fa","name":"test0","chain":[{"balance":811,"height":6212}]}]
[pre round account info:] [{"_id":"5afe91c4d4a30e1af449c5fa","name":"test0","chain":[{"balance":0,"height":0}]}]
START
CONNECTED
┌ [test0] [ 6214, 693 ]
│ ┌ [test1] [ 6214, 844 ]
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ insertRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ insertRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6215, 839 ]
│ ┌ [test1] [ 6215, 78 ]
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ insertRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ insertRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6215, 138 ]
│ ┌ [test1] [ 6215, 677 ]
│ │ updateRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6216, 88 ]
│ ┌ [test1] [ 6216, 16 ]
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ updateRes { n: 0, nModified: 0, ok: 1 }
│ │ insertRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ insertRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
┌ [test0] [ 6216, 845 ]
│ ┌ [test1] [ 6216, 7 ]
│ │ updateRes { n: 1, nModified: 1, ok: 1 }
└─┼ recode update/insert finished.
│ updateRes { n: 1, nModified: 1, ok: 1 }
└ recode update/insert finished.
UPDATE DONE.
[cur round account info:] [{"_id":"5afe91c4d4a30e1af449c5fa","name":"test0","chain":[{"balance":845,"height":6216}]}]
[pre round account info:] [{"_id":"5afe91c4d4a30e1af449c5fa","name":"test0","chain":[{"balance":811,"height":6212}]}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment