node

node

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
javascript/jQuery

javascript/jQuery

一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。
MongoDB

MongoDB

MongoDB 是一个基于分布式文件存储的数据库
openstack

openstack

OpenStack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。
VUE

VUE

一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。
bootstrap

bootstrap

Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.
HTML

HTML

超文本标记语言,标准通用标记语言下的一个应用。
CSS/SASS/SCSS/Less

CSS/SASS/SCSS/Less

层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。
PHP

PHP

PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执
每天进步一点点

每天进步一点点

乌法把门的各累笑寂静
求职招聘

求职招聘

猎头招聘专用栏目
Python

Python

一种解释型、面向对象、动态数据类型的高级程序设计语言。

queries 分离函数 适用 mongoose

Nodejslopo1983 发表了文章 • 0 个评论 • 358 次浏览 • 2018-10-17 21:34 • 来自相关话题

? // app/extend/helper.js
/**
* GET querys 分离函数
* @param {String} pages 分页 [上一页最后一个数据的_id,分页数量] 分页数量默认为10
* @param {String} fields 需要展示的字段 a,b,c,d
* @param {String} unFields 不需要展示的字段 a,b,c,d
* @param {String} querys 查询条件 如 a=1&b=2&c=3
* @param {String} orderBy 排序字段
* @param {String} sort 排序方式【1:正序,-1:倒序】(必须与prderBy同时出现)
* @param {String} dates 时间范围/时间查询 [开始时间,结束时间]/查询时间
*
* @version 1.0.1
* 2018/10/17 修改返回值类型可直接供mongoose使用
*
* @example
* GET /user/?orderBy=compName&sort=-1&pages=20,1&fields=compName,compAuth,compEmail&unFields=status&dates=2018-8-5&name=lopo
* @return {Object}
* {
* querys: { name: 'lopo' },
* select: { compName: 1, compAuth: 1, compEmail: 1, status: 0 },
* pages: { marker: '1', limit: '20' },
* sort: { compName: '-1' },
* dates: '2018-8-5'
* }
*/
queryParamFn(querys) {
const mapFN = (str) => (field, val) => str[field].split(',').reduce((a, b) => { a<strong> = val; return a }, {});
let strToArr = mapFN(querys);
const pages = !!querys.pages && querys.pages;
const orderBy = !!querys.orderBy && querys.orderBy;
const sort = !!querys.sort && querys.sort;
const dates = !!querys.dates && querys.dates;
const fields = !!querys.fields ? strToArr('fields', 1) : {};
const unFields = !!querys.unFields ? strToArr('unFields', 0) : {};
const dateFn = () => {
if (!!dates) {
const ARR = dates.split(',');
return ARR.length === 2 ? { '$gte': ARR[1], '$lte': ARR[0] } : `${ARR}`
}
}
const sortFn = () => {
let OBJ = {};
if (!!orderBy) {
OBJ[orderBy] = sort;
return OBJ
}
return OBJ || {}
}
delete querys.pages;
delete querys.fields;
delete querys.unFields;
delete querys.orderBy;
delete querys.sort;
delete querys.dates;
return {
'querys': querys || {},
'select': { ...fields, ...unFields },
...(!!pages && {
'pages': {
'marker': pages.split(',')[1] || undefined,
'limit': pages.split(',')[0] || 10
}
}),
...!!orderBy && {
'sort': sortFn()
},
...!!dates && {
'dates': dateFn()
}
}
} 查看全部
?
    // app/extend/helper.js
/**
* GET querys 分离函数
* @param {String} pages 分页 [上一页最后一个数据的_id,分页数量] 分页数量默认为10
* @param {String} fields 需要展示的字段 a,b,c,d
* @param {String} unFields 不需要展示的字段 a,b,c,d
* @param {String} querys 查询条件 如 a=1&b=2&c=3
* @param {String} orderBy 排序字段
* @param {String} sort 排序方式【1:正序,-1:倒序】(必须与prderBy同时出现)
* @param {String} dates 时间范围/时间查询 [开始时间,结束时间]/查询时间
*
* @version 1.0.1
* 2018/10/17 修改返回值类型可直接供mongoose使用
*
* @example
* GET /user/?orderBy=compName&sort=-1&pages=20,1&fields=compName,compAuth,compEmail&unFields=status&dates=2018-8-5&name=lopo
* @return {Object}
* {
* querys: { name: 'lopo' },
* select: { compName: 1, compAuth: 1, compEmail: 1, status: 0 },
* pages: { marker: '1', limit: '20' },
* sort: { compName: '-1' },
* dates: '2018-8-5'
* }
*/
queryParamFn(querys) {
const mapFN = (str) => (field, val) => str[field].split(',').reduce((a, b) => { a<strong> = val; return a }, {});
let strToArr = mapFN(querys);
const pages = !!querys.pages && querys.pages;
const orderBy = !!querys.orderBy && querys.orderBy;
const sort = !!querys.sort && querys.sort;
const dates = !!querys.dates && querys.dates;
const fields = !!querys.fields ? strToArr('fields', 1) : {};
const unFields = !!querys.unFields ? strToArr('unFields', 0) : {};
const dateFn = () => {
if (!!dates) {
const ARR = dates.split(',');
return ARR.length === 2 ? { '$gte': ARR[1], '$lte': ARR[0] } : `${ARR}`
}
}
const sortFn = () => {
let OBJ = {};
if (!!orderBy) {
OBJ[orderBy] = sort;
return OBJ
}
return OBJ || {}
}
delete querys.pages;
delete querys.fields;
delete querys.unFields;
delete querys.orderBy;
delete querys.sort;
delete querys.dates;
return {
'querys': querys || {},
'select': { ...fields, ...unFields },
...(!!pages && {
'pages': {
'marker': pages.split(',')[1] || undefined,
'limit': pages.split(',')[0] || 10
}
}),
...!!orderBy && {
'sort': sortFn()
},
...!!dates && {
'dates': dateFn()
}
}
}

mongo TTL 索引

mongodblopo1983 发表了文章 • 0 个评论 • 395 次浏览 • 2018-10-15 23:48 • 来自相关话题

TTL索引是MongoDB中一种特殊的索引, 可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,
并且字段类型必须是date类型或者包含有date类型的数组(如果数组中包含多个date类型字段,则取最早时间为过期时间)
官网介绍链接:https://docs.mongodb.com/v3.2/core/index-ttl/
?
①TTL索引是单字段索引,混合索引不支持TTL,并且也会忽略expireAfterSeconds属性②在_id 主键上不能建立TTL索引③在capped collection中不能建立TTL索引,因为MongoDB不能从capped collection中删除文档④你不能使用createIndex()去更改已经存在的TTL索引的expireAfterSeconds值,如果想更改expireAfterSeconds,可以使用collMod命令,否则你只能删除索引,然后重建了⑤你不能在已有索引的字段上再创建TTL索引了,如果你想把非TTL索引改为TTL索引,那就只能删除重建索引了
?
?db.getCollection('smscodes').ensureIndex({'expiresIn':1},{"expireAfterSeconds":60*1})
MongoDB 权威指南的语法 错误 列为:expireAfterSecs 貌似新版的 应该为如上代码 查看全部
TTL索引是MongoDB中一种特殊的索引, 可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,
并且字段类型必须是date类型或者包含有date类型的数组(如果数组中包含多个date类型字段,则取最早时间为过期时间)

官网介绍链接:https://docs.mongodb.com/v3.2/core/index-ttl/


?
  • ①TTL索引是单字段索引,混合索引不支持TTL,并且也会忽略expireAfterSeconds属性
  • ②在_id 主键上不能建立TTL索引
  • ③在capped collection中不能建立TTL索引,因为MongoDB不能从capped collection中删除文档
  • ④你不能使用createIndex()去更改已经存在的TTL索引的expireAfterSeconds值,如果想更改expireAfterSeconds,可以使用collMod命令,否则你只能删除索引,然后重建了
  • ⑤你不能在已有索引的字段上再创建TTL索引了,如果你想把非TTL索引改为TTL索引,那就只能删除重建索引了

?
?
db.getCollection('smscodes').ensureIndex({'expiresIn':1},{"expireAfterSeconds":60*1})

MongoDB 权威指南的语法 错误 列为:expireAfterSecs 貌似新版的 应该为如上代码

mongo 插入多维数组 唯一 $ne+$push

mongodblopo1983 发表了文章 • 0 个评论 • 308 次浏览 • 2018-09-28 18:22 • 来自相关话题

mongo $addToSet 用于处理普通数组不重复的问题
但是遇到 多维的就会出现问题
?
故只能通过$ne+$push的方式来解决
?
代码如下(egg2.x mongoose5.x)

Schemaconst AllPsListSchema = new Schema({
// 分类中文名称
psName: {
type: String,
required: [true, '服务名称不能为空'],
unique: true,
},
// 分类英文名称
psEnName: {
type: String,
},
// 服务状态 [0/停用,1/正常,2/维护,3/下线]
psState: {
type: Number,
default: 1
},
// 服务子类
psChild: [{
// 产品/服务名称
name: {
type: String,
required: [true, '服务/产品名称不能为空'],
unique: true
},
// 产品/服务英文名称
enName: {
type: String,
required: [true, '服务/产品英文名称不能为空'],
unique: true
},
// 服务状态 [0/停用,1/正常,2/维护,3/下线]
state: {
type: Number,
default: 1
},
// [0/删除,1/锁定,2/正常] 1/锁定意思为不可删除,系统保留
status: {
type: Number,
default: 2
}
}],
// [0:删除,1:锁定,2:正常] 1/锁定意思为不可删除,系统保留
status: {
type: Number,
default: 2
}
}, {
timestamps: {
createdAt: 'created',
updatedAt: 'updated'
}
})
statics
? creatPSChild: async function (_id, bodys) {
const result = await this.findOneAndUpdate({ _id, 'psChild.name': { $ne: bodys.name }, 'psChild.enName': { $ne: bodys.enName } }, {
$push: {
'psChild': bodys
}
});
return { data: result }
} 查看全部
mongo $addToSet 用于处理普通数组不重复的问题
但是遇到 多维的就会出现问题
?
故只能通过$ne+$push的方式来解决
?
代码如下(egg2.x mongoose5.x)

Schema
const AllPsListSchema = new Schema({
// 分类中文名称
psName: {
type: String,
required: [true, '服务名称不能为空'],
unique: true,
},
// 分类英文名称
psEnName: {
type: String,
},
// 服务状态 [0/停用,1/正常,2/维护,3/下线]
psState: {
type: Number,
default: 1
},
// 服务子类
psChild: [{
// 产品/服务名称
name: {
type: String,
required: [true, '服务/产品名称不能为空'],
unique: true
},
// 产品/服务英文名称
enName: {
type: String,
required: [true, '服务/产品英文名称不能为空'],
unique: true
},
// 服务状态 [0/停用,1/正常,2/维护,3/下线]
state: {
type: Number,
default: 1
},
// [0/删除,1/锁定,2/正常] 1/锁定意思为不可删除,系统保留
status: {
type: Number,
default: 2
}
}],
// [0:删除,1:锁定,2:正常] 1/锁定意思为不可删除,系统保留
status: {
type: Number,
default: 2
}
}, {
timestamps: {
createdAt: 'created',
updatedAt: 'updated'
}
})

statics
?
        creatPSChild: async function (_id, bodys) {
const result = await this.findOneAndUpdate({ _id, 'psChild.name': { $ne: bodys.name }, 'psChild.enName': { $ne: bodys.enName } }, {
$push: {
'psChild': bodys
}
});
return { data: result }
}

mongodb 备份还原

mongodblopo1983 发表了文章 • 0 个评论 • 306 次浏览 • 2018-09-20 16:58 • 来自相关话题

备份
?mongodump -h dbhost -d dbname -o dbdir
?
上述语法中:-h MongDB所在服务器,可以附带指定端口号‘:port’

-d 需要备份的数据库实例

-o 备份数据存放的位置

如果以上参数都不指定,默认备份127.0.0.1端口号27017的所有数据库到当前的dump目录C:\Program Files\MongoDB\Server\4.0>mongodump
2018-09-20T16:55:53.312+0800 writing admin.system.version to
2018-09-20T16:55:53.356+0800 done dumping admin.system.version (1 document)
2018-09-20T16:55:53.357+0800 writing test.servicebills to
2018-09-20T16:55:53.357+0800 writing test.smslists to
2018-09-20T16:55:53.357+0800 writing test.companylogs to
2018-09-20T16:55:53.357+0800 writing test.smssigns to
2018-09-20T16:55:53.370+0800 done dumping test.companylogs (106 documents)
2018-09-20T16:55:53.370+0800 writing test.companies to
2018-09-20T16:55:53.374+0800 done dumping test.servicebills (347 documents)
2018-09-20T16:55:53.374+0800 writing test.smstemps to
2018-09-20T16:55:53.375+0800 done dumping test.companies (5 documents)
2018-09-20T16:55:53.376+0800 writing test.smsmailcodes to
2018-09-20T16:55:53.385+0800 done dumping test.smstemps (3 documents)
2018-09-20T16:55:53.385+0800 writing test.admins to
2018-09-20T16:55:53.399+0800 done dumping test.smsmailcodes (2 documents)
2018-09-20T16:55:53.399+0800 writing test.users to
2018-09-20T16:55:53.405+0800 done dumping test.admins (1 document)
2018-09-20T16:55:53.405+0800 writing test.complicenses to
2018-09-20T16:55:53.423+0800 done dumping test.users (1 document)
2018-09-20T16:55:53.423+0800 writing test.smscodes to
2018-09-20T16:55:53.429+0800 done dumping test.complicenses (1 document)
2018-09-20T16:55:53.429+0800 writing test.tokens to
2018-09-20T16:55:53.440+0800 done dumping test.smscodes (1 document)
2018-09-20T16:55:53.440+0800 writing test.zones to
2018-09-20T16:55:53.444+0800 done dumping test.zones (0 documents)
2018-09-20T16:55:53.444+0800 writing test.smshistories to
2018-09-20T16:55:53.447+0800 done dumping test.tokens (1 document)
2018-09-20T16:55:53.448+0800 done dumping test.smshistories (0 documents)
2018-09-20T16:55:54.392+0800 done dumping test.smssigns (15 documents)
2018-09-20T16:55:54.402+0800 done dumping test.smslists (202 documents)
?
还原
?mongorestore -h hostname:port -d dbname <path>
?一些重要的参数-h[:port] 指定MongoDB所在的服务器地址,默认为localhost

-d 需要恢复的数据库

--drop 恢复的时候先删除当前数据库,然后恢复备份,慎重操作

<path> 设置备份数据的位置,和下边的参数有冲突


--dir 指定备份的目录,和上边的参数有冲突
?C:\Program Files\MongoDB\Server\4.0>mongorestore -h IP:port --drop --dir ./dump
2018-09-20T16:57:17.847+0800 preparing collections to restore from
2018-09-20T16:57:17.898+0800 reading metadata for test.servicebills from dump\test\servicebills.metadata.json
2018-09-20T16:57:17.898+0800 reading metadata for test.companylogs from dump\test\companylogs.metadata.json
2018-09-20T16:57:17.899+0800 reading metadata for test.smslists from dump\test\smslists.metadata.json
2018-09-20T16:57:17.899+0800 reading metadata for test.smssigns from dump\test\smssigns.metadata.json
2018-09-20T16:57:17.900+0800 restoring test.servicebills from dump\test\servicebills.bson
2018-09-20T16:57:17.900+0800 restoring test.companylogs from dump\test\companylogs.bson
2018-09-20T16:57:17.900+0800 restoring test.smslists from dump\test\smslists.bson
2018-09-20T16:57:17.900+0800 restoring test.smssigns from dump\test\smssigns.bson 查看全部
备份
?
mongodump -h dbhost -d dbname -o dbdir

?
上述语法中:-h MongDB所在服务器,可以附带指定端口号‘:port’

-d 需要备份的数据库实例

-o 备份数据存放的位置

如果以上参数都不指定,默认备份127.0.0.1端口号27017的所有数据库到当前的dump目录
C:\Program Files\MongoDB\Server\4.0>mongodump
2018-09-20T16:55:53.312+0800 writing admin.system.version to
2018-09-20T16:55:53.356+0800 done dumping admin.system.version (1 document)
2018-09-20T16:55:53.357+0800 writing test.servicebills to
2018-09-20T16:55:53.357+0800 writing test.smslists to
2018-09-20T16:55:53.357+0800 writing test.companylogs to
2018-09-20T16:55:53.357+0800 writing test.smssigns to
2018-09-20T16:55:53.370+0800 done dumping test.companylogs (106 documents)
2018-09-20T16:55:53.370+0800 writing test.companies to
2018-09-20T16:55:53.374+0800 done dumping test.servicebills (347 documents)
2018-09-20T16:55:53.374+0800 writing test.smstemps to
2018-09-20T16:55:53.375+0800 done dumping test.companies (5 documents)
2018-09-20T16:55:53.376+0800 writing test.smsmailcodes to
2018-09-20T16:55:53.385+0800 done dumping test.smstemps (3 documents)
2018-09-20T16:55:53.385+0800 writing test.admins to
2018-09-20T16:55:53.399+0800 done dumping test.smsmailcodes (2 documents)
2018-09-20T16:55:53.399+0800 writing test.users to
2018-09-20T16:55:53.405+0800 done dumping test.admins (1 document)
2018-09-20T16:55:53.405+0800 writing test.complicenses to
2018-09-20T16:55:53.423+0800 done dumping test.users (1 document)
2018-09-20T16:55:53.423+0800 writing test.smscodes to
2018-09-20T16:55:53.429+0800 done dumping test.complicenses (1 document)
2018-09-20T16:55:53.429+0800 writing test.tokens to
2018-09-20T16:55:53.440+0800 done dumping test.smscodes (1 document)
2018-09-20T16:55:53.440+0800 writing test.zones to
2018-09-20T16:55:53.444+0800 done dumping test.zones (0 documents)
2018-09-20T16:55:53.444+0800 writing test.smshistories to
2018-09-20T16:55:53.447+0800 done dumping test.tokens (1 document)
2018-09-20T16:55:53.448+0800 done dumping test.smshistories (0 documents)
2018-09-20T16:55:54.392+0800 done dumping test.smssigns (15 documents)
2018-09-20T16:55:54.402+0800 done dumping test.smslists (202 documents)

?
还原
?
mongorestore -h hostname:port -d dbname <path>

?一些重要的参数-h[:port] 指定MongoDB所在的服务器地址,默认为localhost

-d 需要恢复的数据库

--drop 恢复的时候先删除当前数据库,然后恢复备份,慎重操作

<path> 设置备份数据的位置,和下边的参数有冲突


--dir 指定备份的目录,和上边的参数有冲突
?
C:\Program Files\MongoDB\Server\4.0>mongorestore -h IP:port --drop --dir ./dump
2018-09-20T16:57:17.847+0800 preparing collections to restore from
2018-09-20T16:57:17.898+0800 reading metadata for test.servicebills from dump\test\servicebills.metadata.json
2018-09-20T16:57:17.898+0800 reading metadata for test.companylogs from dump\test\companylogs.metadata.json
2018-09-20T16:57:17.899+0800 reading metadata for test.smslists from dump\test\smslists.metadata.json
2018-09-20T16:57:17.899+0800 reading metadata for test.smssigns from dump\test\smssigns.metadata.json
2018-09-20T16:57:17.900+0800 restoring test.servicebills from dump\test\servicebills.bson
2018-09-20T16:57:17.900+0800 restoring test.companylogs from dump\test\companylogs.bson
2018-09-20T16:57:17.900+0800 restoring test.smslists from dump\test\smslists.bson
2018-09-20T16:57:17.900+0800 restoring test.smssigns from dump\test\smssigns.bson

mongodb 数组操作

mongodblopo1983 发表了文章 • 0 个评论 • 341 次浏览 • 2018-09-17 23:00 • 来自相关话题

1. 添加
db.test.update({'_id':id},{
$push:{'arr':{'name':'value'}}
})2.修改
db.test.update({'_id':id,arr.name:'name'},{
$set:{'arr.$.name':'newName'}
})3.删除(多维数组删除)
db.test.update({'_id':id},{
$pull:{arr:{'name':'value'}}
})
? 查看全部
1. 添加
db.test.update({'_id':id},{
$push:{'arr':{'name':'value'}}
})
2.修改
db.test.update({'_id':id,arr.name:'name'},{
$set:{'arr.$.name':'newName'}
})
3.删除(多维数组删除)
db.test.update({'_id':id},{
$pull:{arr:{'name':'value'}}
})

?

MongoDB 聚合统计

mongodblopo1983 发表了文章 • 0 个评论 • 357 次浏览 • 2018-09-14 14:56 • 来自相关话题

聚合(aggregate)主要用于计算数据,类似sql中的sum(),avg()。
db.集合名称.aggregate({管道:{表达式}})
?管道
?
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入 在mongodb中,管道具有同样的作用,文档处理完毕后,通过管道进行下一次处理 常用管道
$group:将集合中的文档分组,可用于统计结果$match:过滤数据,只输出符合条件的文档$project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果$sort:将输入文档排序后输出$limit:限制聚合管道返回的文档数$skip:跳过指定数量的文档,并返回余下的文档$unwind:将数组类型的字段进行拆分
?
?
表达式
?
处理输入文档并输出
?
$sum:计算总和?
$avg:计算平均值?
$min:获取最小值?
$max:获取最大值?
$push:在结果文档中插入值到一个数组中?
$first:根据资源文档的排序获取第一个文档数据?
$last:根据资源文档的排序获取最后一个文档数据?
例子
表结构:
const compAccountDealrecordSchema = new Schema({
// billing 订单标识
numer: {
type: String
},
// 公司名称
_comp: {
type: Schema.Types.ObjectId,
ref: 'Company',
required: true,
index: true
},
// 消费金额
amount: {
type: Number,
default: 0.00
},
// 账户余额
balance: {
type: Number,
default: 0.00
},
// 渠道类型
channelType: {
type: String,
default: 'BALANCE'
},
// 日账单
dailyBill: {
type: Boolean,
default: false
},
// 按需扣费账单
debtDeduct: {
type: Boolean,
default: false
},
// 描述
detail: {
type: String,
default: ''
},
// 账单
detailRequest: {
type: Schema.Types.ObjectId,
ref: 'Company',
},
// 账单类型
detailType: {
type: String,
default: 'LINK'
},
// 账单链接
detailUrl: {
type: String,
default: ''
},
// 订单ID
orderId: {
type: Schema.Types.ObjectId,
ref: 'comp_account_billing_order'
},
// 账单产品详细
serviceItem: [],
// 产品类型
serviceType: {},
// 交易类型 [RECHARGE:收入,CONSUME:支出]
transactionType: {
type: String,
default: 'CONSUME'
},
// 备注
remark: {

}
}, {
timestamps: {
createdAt: 'created',
updatedAt: 'updated'
}
});静态方法
compAccountDealrecordSchema.statics = {
getAll: async function(queryMix, _comp) {
const {
querys,
select
} = queryMix;
const models = this.find({
...!!_comp && {
_comp
}
})
.sort({
'_id': -1,
});
try {
return {
data: {
result: await models,
totalCount: await models.count()
}
};
} catch (error) {
return error
}
},
getOne: async function(_id, _comp) {
const MODELS = this.findOne({..._comp && {
_comp
},
_id
}).sort({
'_id': -1
});
try {
return {
data: await MODELS
}
} catch (error) {
return error
}
},
createOne: async function(bodys) {
return await this.create(bodys)
},
backCashAdd: async function(bodys, auth) {
const {
_comp,
serviceBillCash,
serviceBillChannel,
serviceBillRemark
} = bodys
// 生成流水
await this.create({
'_comp': _comp,
'serviceBillProduct': '-',
'serviceBillType': '充值',
'serviceBillCash': `+${serviceBillCash}`,
'serviceBillChannel': `${serviceBillChannel}`,
'serviceBillRemark': `手工入款/n${serviceBillChannel}/n${serviceBillRemark}`,
'_admin': auth.id
});
return await ctx.model.Company.cashFN(serviceBillCash, auth, 'cash', 'add', _comp);
},
seachComp: async function(name) {
return await ctx.model.Company.find({
'compName': eval(`/${name}.*/i`)
}, {
'compEmail': 1,
'compName': 1,
'compPhone': 1
})
},
// 图表数据
/**
*
* @param {*} type 订单类型
* @param {*} scope 月份计算
* @param {*} _comp
*/
getPanelChart: async function(type = 'all', classify = "line", _comp) {
const MODEL = this.aggregate([
...classify === 'pie' ? [{
$unwind: `$serviceItem`,
}] : [],
...[{
$match: {
'_comp': mongoose.Types.ObjectId(_comp),
'created': {
"$gt": new Date(subtractMoment(1, 'month'))
},
"channelType": "CASH",
...type !== 'all' && {
'serviceItem.serviceType': type
}
}
},
{
$project: {
'_comp': 1,
'amount': 1,
'created': 1,
"serviceItem": 1,
'day': {
$substr: ["$created", 0, 10]
}
}
},
{
$group: {
...classify === "line" ? {
'_id': `$day`
} : {
'_id': '$serviceItem.serviceType'
},
'count': {
$sum: classify === 'pie' ? '$serviceItem.price' : '$amount'
}
}
},
{
$project: {
...classify === "line" ? {
'days': '$_id'
} : {
'serviceType': '$_id'
},
'count': 1,
_id: 0
}
},
{
$sort: {
'days': 1
}
}
]
]);
try {
const lastMonth = subtractMoment(1, 'month', 'subtract');
const DateMaps = (getDayAll(lastMonth, new Date()));
const data = await MODEL;
return {
...classify === 'pie' ? {
data
} : {
'data': {
datas: DateMaps.reduce((a, b) => {
let count;
data.forEach(e => {
if (e.days === b) count = e.count
});
a.push(count ? count : 0);
return a
}, []),
dates: DateMaps
}
}
}
} catch (error) {
console.log(error)
}
},
/**
* @param {String} type 产品类型()
*/
getCashCount: async function(ctx, auth, type, _comp) {
const {
endDate
} = ctx.helper.getPrevMoment('month');
const yestoday = ctx.helper.subtractMoment(1, 'day');
const typeoObj = type === 'all' ? {} : {
'serviceBillProduct': type,
'_comp': mongoose.Types.ObjectId(_comp ? _comp : auth.id)
};
return [(await this.aggregate([{
$match: {...typeoObj,
'created': {
"$gt": new Date(endDate)
},
'serviceBillType': '消费'
}
},
{
$group: {
'_id': {
'_comp': auth.id
},
'monthCashSum': {
$sum: "$serviceBillCash"
}
}
},
{
$project: {
'_id': 0
}
}
]))[0], (await this.aggregate([{
$match: {...typeoObj,
'created': {
"$gt": new Date(yestoday)
},
'serviceBillType': '消费'
}
},
{
$group: {
'_id': {
'_comp': auth.id
},
'dayCashSum': {
$sum: "$serviceBillCash"
}
}
},
{
$project: {
'_id': 0
}
},
]))[0]]
},
}; 查看全部

聚合(aggregate)主要用于计算数据,类似sql中的sum(),avg()。


db.集合名称.aggregate({管道:{表达式}})

?管道
?
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入 在mongodb中,管道具有同样的作用,文档处理完毕后,通过管道进行下一次处理 常用管道
  • $group:将集合中的文档分组,可用于统计结果
  • $match:过滤数据,只输出符合条件的文档
  • $project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
  • $sort:将输入文档排序后输出
  • $limit:限制聚合管道返回的文档数
  • $skip:跳过指定数量的文档,并返回余下的文档
  • $unwind:将数组类型的字段进行拆分

?
?
表达式
?
处理输入文档并输出
?
$sum:计算总和?
$avg:计算平均值?
$min:获取最小值?
$max:获取最大值?
$push:在结果文档中插入值到一个数组中?
$first:根据资源文档的排序获取第一个文档数据?
$last:根据资源文档的排序获取最后一个文档数据?
例子
表结构:
 const compAccountDealrecordSchema = new Schema({
// billing 订单标识
numer: {
type: String
},
// 公司名称
_comp: {
type: Schema.Types.ObjectId,
ref: 'Company',
required: true,
index: true
},
// 消费金额
amount: {
type: Number,
default: 0.00
},
// 账户余额
balance: {
type: Number,
default: 0.00
},
// 渠道类型
channelType: {
type: String,
default: 'BALANCE'
},
// 日账单
dailyBill: {
type: Boolean,
default: false
},
// 按需扣费账单
debtDeduct: {
type: Boolean,
default: false
},
// 描述
detail: {
type: String,
default: ''
},
// 账单
detailRequest: {
type: Schema.Types.ObjectId,
ref: 'Company',
},
// 账单类型
detailType: {
type: String,
default: 'LINK'
},
// 账单链接
detailUrl: {
type: String,
default: ''
},
// 订单ID
orderId: {
type: Schema.Types.ObjectId,
ref: 'comp_account_billing_order'
},
// 账单产品详细
serviceItem: [],
// 产品类型
serviceType: {},
// 交易类型 [RECHARGE:收入,CONSUME:支出]
transactionType: {
type: String,
default: 'CONSUME'
},
// 备注
remark: {

}
}, {
timestamps: {
createdAt: 'created',
updatedAt: 'updated'
}
});
静态方法
    compAccountDealrecordSchema.statics = {
getAll: async function(queryMix, _comp) {
const {
querys,
select
} = queryMix;
const models = this.find({
...!!_comp && {
_comp
}
})
.sort({
'_id': -1,
});
try {
return {
data: {
result: await models,
totalCount: await models.count()
}
};
} catch (error) {
return error
}
},
getOne: async function(_id, _comp) {
const MODELS = this.findOne({..._comp && {
_comp
},
_id
}).sort({
'_id': -1
});
try {
return {
data: await MODELS
}
} catch (error) {
return error
}
},
createOne: async function(bodys) {
return await this.create(bodys)
},
backCashAdd: async function(bodys, auth) {
const {
_comp,
serviceBillCash,
serviceBillChannel,
serviceBillRemark
} = bodys
// 生成流水
await this.create({
'_comp': _comp,
'serviceBillProduct': '-',
'serviceBillType': '充值',
'serviceBillCash': `+${serviceBillCash}`,
'serviceBillChannel': `${serviceBillChannel}`,
'serviceBillRemark': `手工入款/n${serviceBillChannel}/n${serviceBillRemark}`,
'_admin': auth.id
});
return await ctx.model.Company.cashFN(serviceBillCash, auth, 'cash', 'add', _comp);
},
seachComp: async function(name) {
return await ctx.model.Company.find({
'compName': eval(`/${name}.*/i`)
}, {
'compEmail': 1,
'compName': 1,
'compPhone': 1
})
},
// 图表数据
/**
*
* @param {*} type 订单类型
* @param {*} scope 月份计算
* @param {*} _comp
*/
getPanelChart: async function(type = 'all', classify = "line", _comp) {
const MODEL = this.aggregate([
...classify === 'pie' ? [{
$unwind: `$serviceItem`,
}] : [],
...[{
$match: {
'_comp': mongoose.Types.ObjectId(_comp),
'created': {
"$gt": new Date(subtractMoment(1, 'month'))
},
"channelType": "CASH",
...type !== 'all' && {
'serviceItem.serviceType': type
}
}
},
{
$project: {
'_comp': 1,
'amount': 1,
'created': 1,
"serviceItem": 1,
'day': {
$substr: ["$created", 0, 10]
}
}
},
{
$group: {
...classify === "line" ? {
'_id': `$day`
} : {
'_id': '$serviceItem.serviceType'
},
'count': {
$sum: classify === 'pie' ? '$serviceItem.price' : '$amount'
}
}
},
{
$project: {
...classify === "line" ? {
'days': '$_id'
} : {
'serviceType': '$_id'
},
'count': 1,
_id: 0
}
},
{
$sort: {
'days': 1
}
}
]
]);
try {
const lastMonth = subtractMoment(1, 'month', 'subtract');
const DateMaps = (getDayAll(lastMonth, new Date()));
const data = await MODEL;
return {
...classify === 'pie' ? {
data
} : {
'data': {
datas: DateMaps.reduce((a, b) => {
let count;
data.forEach(e => {
if (e.days === b) count = e.count
});
a.push(count ? count : 0);
return a
}, []),
dates: DateMaps
}
}
}
} catch (error) {
console.log(error)
}
},
/**
* @param {String} type 产品类型()
*/
getCashCount: async function(ctx, auth, type, _comp) {
const {
endDate
} = ctx.helper.getPrevMoment('month');
const yestoday = ctx.helper.subtractMoment(1, 'day');
const typeoObj = type === 'all' ? {} : {
'serviceBillProduct': type,
'_comp': mongoose.Types.ObjectId(_comp ? _comp : auth.id)
};
return [(await this.aggregate([{
$match: {...typeoObj,
'created': {
"$gt": new Date(endDate)
},
'serviceBillType': '消费'
}
},
{
$group: {
'_id': {
'_comp': auth.id
},
'monthCashSum': {
$sum: "$serviceBillCash"
}
}
},
{
$project: {
'_id': 0
}
}
]))[0], (await this.aggregate([{
$match: {...typeoObj,
'created': {
"$gt": new Date(yestoday)
},
'serviceBillType': '消费'
}
},
{
$group: {
'_id': {
'_comp': auth.id
},
'dayCashSum': {
$sum: "$serviceBillCash"
}
}
},
{
$project: {
'_id': 0
}
},
]))[0]]
},
};

webhook

每天进步一点点lopo1983 发表了文章 • 0 个评论 • 291 次浏览 • 2018-08-16 18:58 • 来自相关话题

rsa_pub
ssh-keygen -t rsa -C example@mail.com
rsa_pub
ssh-keygen -t rsa -C example@mail.com

汉字转拼音 字典整理

每天进步一点点lopo1983 发表了文章 • 0 个评论 • 380 次浏览 • 2018-08-02 22:08 • 来自相关话题

数据源:http://www.ziyexing.com/files-7/tools/chinese_ziku.htm??
代码: const zd = [...document.querySelectorAll('font b')].map(e => e.nextSibling.nextSibling).filter(e => e != null).map(e => {
const OBJ = {};
OBJ[e.previousSibling.previousSibling.innerText] = ([...e.data.trim().replace(/\([^\)]*\)/g, "")].reduce((a, b) => a += '\\u' + b.charCodeAt(0).toString(16), ''));
return OBJ
}); 查看全部
数据源:http://www.ziyexing.com/files-7/tools/chinese_ziku.htm??
代码:
        const zd = [...document.querySelectorAll('font b')].map(e => e.nextSibling.nextSibling).filter(e => e != null).map(e => {
const OBJ = {};
OBJ[e.previousSibling.previousSibling.innerText] = ([...e.data.trim().replace(/\([^\)]*\)/g, "")].reduce((a, b) => a += '\\u' + b.charCodeAt(0).toString(16), ''));
return OBJ
});

centos nodejs

每天进步一点点lopo1983 发表了文章 • 0 个评论 • 420 次浏览 • 2018-07-24 20:36 • 来自相关话题

1.curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -2.sudo yum -y install nodejs3.npm config set registry https://registry.npm.taobao.org 查看全部
1.
curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
2.
sudo yum -y install nodejs
3.
npm config set registry https://registry.npm.taobao.org

骚骚的reduce

每天进步一点点lopo1983 发表了文章 • 0 个评论 • 500 次浏览 • 2018-07-05 02:04 • 来自相关话题

arr.reduce(callback[, initialValue])reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:
accumulatorcurrentValuecurrentIndexarray

回调函数第一次执行时,accumulator?和currentValue的取值有两种情况:调用reduce时提供initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;没有提供?initialValue,accumulator取数组中的第一个值,currentValue取数组中的第二个值
?
计算某个字符出现的次数[...'abcdaabdcfggtre'].reduce((a,b)=>{a[b]?a[b]++:a[b]=1;return a},{})字母游戏const anagrams = str => {
if (str.length <= 2) {
return str.length === 2 ? [str, str[1] + str[0]] : str;
}
return str.split("").reduce((acc, letter, i) => {
return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));
}, );
}

anagrams("abc"); 累加器const sum = arr => arr.reduce((acc, val) => acc + val, 0);
sum([1, 2, 3]);计数器const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
countOccurrences([1, 2, 3, 2, 2, 5, 1], 1);函数柯里化const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);

curry(Math.pow)(2)(10);
curry(Math.min, 3)(10)(50)(2);?
通过判断函数的参数取得当前函数的length(当然也可以自己指定),如果所传的参数比当前参数少,则继续递归下面,同时储存上一次传递的参数。


数组扁平化const deepFlatten = arr =>
arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), );
deepFlatten([1, [2, [3, 4, [5, 6]]]]);


生成菲波列契数组const fibonacci = n => Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), );
fibonacci(5);pipe函数生成器const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg);
pipe(btoa, x => x.toUpperCase())("Test");?
通过对传递的参数进行函数加工,之后将加工之后的数据作为下一个函数的参数,这样层层传递下去。


compose函数生成器const dispatch = action => {
console.log('action', action);
return action;
}

const middleware1 = dispatch => {
return action => {
console.log("middleware1");
const result = dispatch(action);
console.log("after middleware1");
return result;
}
}

const middleware2 = dispatch => {
return action => {
console.log("middleware2");
const result = dispatch(action);
console.log("after middleware2");
return result;
}
}

const middleware3 = dispatch => {
return action => {
console.log("middleware3");
const result = dispatch(action);
console.log("after middleware3");
return result;
}
}

const compose = middlewares => middlewares.reduce((a, b) => args => a(b(args)))

const middlewares = [middleware1, middleware2, middleware3];
const afterDispatch = compose(middlewares)(dispatch);

const testAction = arg => {
return { type: "TEST_ACTION", params: arg };
};
afterDispatch(testAction("1111"));?
数据加工函数const reducers = {
totalInEuros: (state, item) => {
return state.euros += item.price * 0.897424392;
},
totalInYen: (state, item) => {
return state.yens += item.price * 113.852;
}
};

const manageReducers = reducers => {
return (state, item) => {
return Object.keys(reducers).reduce((nextState, key) => {
reducers[key](state, item);
return state;
}, {})
}
}

const bigTotalPriceReducer = manageReducers(reducers);
const initialState = { euros: 0, yens: 0 };
const items = [{ price: 10 }, { price: 120 }, { price: 1000 }];
const totals = items.reduce(bigTotalPriceReducer, initialState);对象空值判断const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o);分组const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
acc[val] = (acc[val] || ).concat(arr);
return acc;
}, {});
groupBy([6.1, 4.2, 6.3], Math.floor);
groupBy(['one', 'two', 'three'], 'length'); 对象过滤const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});

pick({ a: 1, b: '2', c: 3 }, ['a', 'c']);promise顺序执行const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());

const delay = d => new Promise(r => setTimeout(r, d));
const print = args => new Promise(r => r(args));
runPromisesInSeries([() => delay(1000), () => delay(2000), () => print('hello')])排序函数const orderBy = (arr, props, orders) =>
[...arr].sort((a, b) =>
props.reduce((acc, prop, i) => {
if (acc === 0) {
const [p1, p2] = orders && orders === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
}
return acc;
}, 0)
);

const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fly', age: 26 }];
orderBy(users, ['name', 'age'], ['asc', 'desc']);
orderBy(users, ['name', 'age']);快速选择器const select = (from, selector) =>
selector.split('.').reduce((prev, cur) => prev && prev[cur], from);

const obj = { selector: { to: { val: 'val to select' } } };
select(obj, 'selector.to.val'); 查看全部
arr.reduce(callback[, initialValue])
reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:
  • accumulator
  • currentValue
  • currentIndex
  • array


回调函数第一次执行时,accumulator?和currentValue的取值有两种情况:调用reduce时提供initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;没有提供?initialValue,accumulator取数组中的第一个值,currentValue取数组中的第二个值
?
计算某个字符出现的次数
[...'abcdaabdcfggtre'].reduce((a,b)=>{a[b]?a[b]++:a[b]=1;return a},{})
字母游戏
const anagrams = str => {
if (str.length <= 2) {
return str.length === 2 ? [str, str[1] + str[0]] : str;
}
return str.split("").reduce((acc, letter, i) => {
return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));
}, );
}

anagrams("abc");
累加器
const sum = arr => arr.reduce((acc, val) => acc + val, 0);
sum([1, 2, 3]);
计数器
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
countOccurrences([1, 2, 3, 2, 2, 5, 1], 1);
函数柯里化
const curry = (fn, arity = fn.length, ...args) => 
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);

curry(Math.pow)(2)(10);
curry(Math.min, 3)(10)(50)(2);
?

通过判断函数的参数取得当前函数的length(当然也可以自己指定),如果所传的参数比当前参数少,则继续递归下面,同时储存上一次传递的参数。




数组扁平化
const deepFlatten = arr =>
arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), );
deepFlatten([1, [2, [3, 4, [5, 6]]]]);


生成菲波列契数组
const fibonacci = n => Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), );
fibonacci(5);
pipe函数生成器
const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg);
pipe(btoa, x => x.toUpperCase())("Test");
?

通过对传递的参数进行函数加工,之后将加工之后的数据作为下一个函数的参数,这样层层传递下去。




compose函数生成器
const dispatch = action => {
console.log('action', action);
return action;
}

const middleware1 = dispatch => {
return action => {
console.log("middleware1");
const result = dispatch(action);
console.log("after middleware1");
return result;
}
}

const middleware2 = dispatch => {
return action => {
console.log("middleware2");
const result = dispatch(action);
console.log("after middleware2");
return result;
}
}

const middleware3 = dispatch => {
return action => {
console.log("middleware3");
const result = dispatch(action);
console.log("after middleware3");
return result;
}
}

const compose = middlewares => middlewares.reduce((a, b) => args => a(b(args)))

const middlewares = [middleware1, middleware2, middleware3];
const afterDispatch = compose(middlewares)(dispatch);

const testAction = arg => {
return { type: "TEST_ACTION", params: arg };
};
afterDispatch(testAction("1111"));
?
数据加工函数
const reducers = {
totalInEuros: (state, item) => {
return state.euros += item.price * 0.897424392;
},
totalInYen: (state, item) => {
return state.yens += item.price * 113.852;
}
};

const manageReducers = reducers => {
return (state, item) => {
return Object.keys(reducers).reduce((nextState, key) => {
reducers[key](state, item);
return state;
}, {})
}
}

const bigTotalPriceReducer = manageReducers(reducers);
const initialState = { euros: 0, yens: 0 };
const items = [{ price: 10 }, { price: 120 }, { price: 1000 }];
const totals = items.reduce(bigTotalPriceReducer, initialState);
对象空值判断
const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o);
分组
const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
acc[val] = (acc[val] || ).concat(arr);
return acc;
}, {});
groupBy([6.1, 4.2, 6.3], Math.floor);
groupBy(['one', 'two', 'three'], 'length');
对象过滤
const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});

pick({ a: 1, b: '2', c: 3 }, ['a', 'c']);
promise顺序执行
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());

const delay = d => new Promise(r => setTimeout(r, d));
const print = args => new Promise(r => r(args));
runPromisesInSeries([() => delay(1000), () => delay(2000), () => print('hello')])
排序函数
const orderBy = (arr, props, orders) =>
[...arr].sort((a, b) =>
props.reduce((acc, prop, i) => {
if (acc === 0) {
const [p1, p2] = orders && orders === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
}
return acc;
}, 0)
);

const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fly', age: 26 }];
orderBy(users, ['name', 'age'], ['asc', 'desc']);
orderBy(users, ['name', 'age']);
快速选择器
const select = (from, selector) =>
selector.split('.').reduce((prev, cur) => prev && prev[cur], from);

const obj = { selector: { to: { val: 'val to select' } } };
select(obj, 'selector.to.val');