Last active
May 18, 2018 08:42
-
-
Save Gaubee/a0a63216eb7cf9cc38fc9542fc334a5e to your computer and use it in GitHub Desktop.
使用数组来链式记录账户的余额
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}]}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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