629 lines
14 KiB
TypeScript
629 lines
14 KiB
TypeScript
import {
|
||
Collection,
|
||
CreateIndexesOptions,
|
||
Db,
|
||
IndexDescription,
|
||
IndexSpecification,
|
||
MongoClient,
|
||
MongoClientOptions,
|
||
ObjectId,
|
||
OptionalId
|
||
} from 'mongodb';
|
||
import {CollectionActionLog, actionLogType} from './module/collection_actionLog';
|
||
import {CollectionEvent, eventType} from './module/collection_event';
|
||
import {CollectionPlayerInfo, playerInfoType} from './module/collection_palyerInfo';
|
||
import {CollectionRecord, recordType} from './module/collection_record';
|
||
import {MongodbCollections} from './module/mongodb';
|
||
import {HuoDongFun} from './public/huodongfun';
|
||
import {zbsGroup} from './api_s2c/hbzb/zbs/fun';
|
||
import {clusterRunOnce} from './clusterUtils';
|
||
import { PublicShared } from './shared/public/public';
|
||
|
||
const indexs: Partial<{ [k in keyof MongodbCollections]: IndexDescription[] }> = {
|
||
item: [
|
||
{
|
||
key: {uid: 1, itemId: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
user: [
|
||
{
|
||
key: {bindUid: 1, sid: 1}, unique: true,
|
||
},
|
||
{
|
||
key: {name: 1}, unique: true,
|
||
},
|
||
{
|
||
key: {uid: 1}, unique: true,
|
||
},
|
||
{
|
||
key: {mapId: 1},
|
||
}
|
||
],
|
||
hero: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
equip: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
shiwu: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
email: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {ttl: 1}, expireAfterSeconds: 15 * 24 * 3600
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
xstask: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
playerInfo: [
|
||
{
|
||
key: {uid: 1, type: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
pata: [
|
||
{
|
||
key: {uid: 1, sid: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
gbtx: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
tanxian: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
cardlog: [
|
||
{
|
||
key: {uid: 1, cardnum: 1}, unique: true
|
||
}
|
||
],
|
||
dxlt: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
jjc: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
playattr: [
|
||
{
|
||
key: {uid: 1, ctype: 1}, unique: true
|
||
}
|
||
],
|
||
gonghui: [
|
||
{
|
||
key: {name: 1}, unique: true
|
||
}
|
||
],
|
||
gonghuiUser: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
gonghuiFb: [
|
||
{
|
||
key: {ghId: 1, fbId: 1}, unique: true
|
||
}
|
||
],
|
||
task: [
|
||
{
|
||
key: {uid: 1, taskid: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
},
|
||
{
|
||
key: {stype: 1}
|
||
},
|
||
{
|
||
key: {pval: 1}
|
||
},
|
||
{
|
||
key: {nval: 1}
|
||
}
|
||
],
|
||
actionLog: [
|
||
{
|
||
key: {uid: 1, type: 1}, unique: true
|
||
}
|
||
],
|
||
syncBtns: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
payLog: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
event: [
|
||
{
|
||
key: {uid: 1, type: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
friend: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
chat: [
|
||
{
|
||
key: {type: 1}, unique: true
|
||
}
|
||
],
|
||
chatLog: [
|
||
{
|
||
key: {uid: 1}
|
||
},
|
||
{
|
||
key: {type: 1}
|
||
}
|
||
],
|
||
slzdGh: [
|
||
{
|
||
key: {ghid: 1}, unique: true
|
||
}
|
||
],
|
||
slzdUser: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
ganhai: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
dayPay: [
|
||
{
|
||
key: {uid: 1, time: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
rankList: [
|
||
{
|
||
key: {type: 1, idKey: 1}, unique: true
|
||
}
|
||
],
|
||
wanted: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
peijian: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
}
|
||
],
|
||
mingdao: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
wjjl: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
zhanling: [
|
||
{
|
||
key: {uid: 1, type: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
hdinfo: [
|
||
{
|
||
key: {hdid: 1}, unique: true
|
||
},
|
||
{
|
||
key: {htype: 1}
|
||
},
|
||
{
|
||
key: {ttype: 1}
|
||
},
|
||
{
|
||
key: {stime: 1}
|
||
},
|
||
{
|
||
key: {etime: 1}
|
||
}
|
||
],
|
||
giftLog: [
|
||
{
|
||
key: {popup_id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {game_user_id: 1}
|
||
}
|
||
],
|
||
loginLog: [
|
||
{
|
||
key: {uid: 1, _id: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
payLogNew: [
|
||
{
|
||
key: {uid: 1, key: 1}
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
kuangdong: [
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
apiCount: [
|
||
{
|
||
key: {api: 1}, unique: true
|
||
}
|
||
],
|
||
weixiuchang: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
player_behavior: [
|
||
{
|
||
key: {uid: 1, type: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
rmbuse: [
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
fightLog: [
|
||
{
|
||
key: {uid: 1, type: 1}
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
},
|
||
{
|
||
key: {ttl: 1}, expireAfterSeconds: 7 * 24 * 3600
|
||
}
|
||
],
|
||
shop: [
|
||
{
|
||
key: {uid: 1, shopId: 1}, unique: true
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
]
|
||
};
|
||
|
||
const crossIndexs: Partial<{ [k in keyof MongodbCollections]: IndexDescription[] }> = {
|
||
email: [
|
||
{
|
||
key: {sid: 1}
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
}
|
||
],
|
||
fightLog: [
|
||
{
|
||
key: {uid: 1, type: 1}
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
},
|
||
{
|
||
key: {ttl: 1}, expireAfterSeconds: 7 * 24 * 3600
|
||
}
|
||
],
|
||
hbzb_user_cross: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
},
|
||
{
|
||
key: {jifen: 1}
|
||
},
|
||
{
|
||
key: {rank: 1}
|
||
},
|
||
{
|
||
key: {zbsgroup: 1}
|
||
}
|
||
],
|
||
hbzb_user_zbs: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
kbzzApplyUser: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
kbzzGroupUser: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
clslCrossUser: [
|
||
{
|
||
key: {uid: 1}, unique: true
|
||
}
|
||
],
|
||
rankList: [
|
||
{
|
||
key: {type: 1, idKey: 1}, unique: true
|
||
},
|
||
{
|
||
key: {valArr: -1}
|
||
},
|
||
],
|
||
wzry_fight: [
|
||
{
|
||
key: {jifen: 1}
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
},
|
||
{
|
||
key: {zkey: 1}
|
||
},
|
||
],
|
||
wzry_user_cross: [
|
||
{
|
||
key: {jifen: 1}
|
||
},
|
||
{
|
||
key: {uid: 1}
|
||
},
|
||
{
|
||
key: {zkey: 1}
|
||
},
|
||
]
|
||
};
|
||
|
||
export async function initMongoDB() {
|
||
//mongodb连接数说明:https://blog.csdn.net/for_cxc/article/details/116859714
|
||
//可结合查看:node_modules\mongodb\lib\connection_string.js
|
||
//maxPoolSize默认值:100
|
||
|
||
let option:MongoClientOptions;
|
||
//跨服只有1个,直接采用默认配置就行
|
||
if(G.argv.serverType != 'cross'){
|
||
if(PublicShared.getOpenServerDay() > 3){
|
||
option = {
|
||
maxPoolSize: 10
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log('connect mongodb ......');
|
||
let client = await MongoClient.connect(G.argv.serverType == 'cross' ? G.config.crossMongodbUrl : G.config.mongodbUrl, option);
|
||
G.mongodb = new _mongodb(client.db(G.config.dbName || ''));
|
||
console.log('connect mongodb succ');
|
||
|
||
|
||
if (G.argv.serverType != 'cross') {
|
||
console.log('connect crossmongodb ......');
|
||
//本服里,维持住跟跨服数据库的链接
|
||
let crossClient = await MongoClient.connect(G.config.crossMongodbUrl,{
|
||
maxPoolSize:10
|
||
});
|
||
G.crossmongodb = new _mongodb(crossClient.db(G.config.corssDBName || ""));
|
||
console.log('connect crossmongodb succ');
|
||
}
|
||
|
||
clusterRunOnce(() => {
|
||
//只在集群的一个进程里进行即可
|
||
setDbIndexes();
|
||
});
|
||
}
|
||
|
||
/**根据配置,设置mongodb的索引 */
|
||
export async function setDbIndexes() {
|
||
let _indexs = G.argv.serverType == 'cross' ? crossIndexs : indexs;
|
||
for (let coll in _indexs) {
|
||
for (let i = 0; i < _indexs[coll].length; i++) {
|
||
let index = _indexs[coll][i];
|
||
|
||
let option = {} as CreateIndexesOptions;
|
||
if (index.unique != null) {
|
||
option.unique = index.unique;
|
||
}
|
||
if (index.expireAfterSeconds != null) {
|
||
option.expireAfterSeconds = index.expireAfterSeconds;
|
||
}
|
||
|
||
try {
|
||
await G.mongodb.collection(coll as keyof MongodbCollections).createIndex(
|
||
index.key,
|
||
option
|
||
);
|
||
console.log('创建索引成功', coll, index);
|
||
} catch (error) {
|
||
if (error.codeName == 'IndexKeySpecsConflict') {
|
||
//当相同索引存在,但是配置(如:unique expireAfterSeconds)不同时,会收到这个报错
|
||
//此时会把原来的索引删除后重建
|
||
console.log('创建索引失败,和已有的索引冲突,尝试删除后重建');
|
||
await G.mongodb.collection(coll as keyof MongodbCollections).dropIndex(index.key);
|
||
|
||
//再试一次,不行只能抛出错误了
|
||
try {
|
||
await G.mongodb.collection(coll as keyof MongodbCollections).createIndex(
|
||
index.key,
|
||
option
|
||
);
|
||
console.log('创建索引成功', coll, index);
|
||
} catch (error) {
|
||
console.log('创建索引失败==>', coll, index, error.message);
|
||
}
|
||
|
||
} else {
|
||
console.log('创建索引失败=>', coll, index, error.message);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
export class _mongodb {
|
||
constructor(private db: Db) {
|
||
|
||
}
|
||
|
||
/**
|
||
* mongodb仿sql查询
|
||
* @param field 需要获取的字段,空数组表示所有字段,如:["uid","lv"]
|
||
* @param from 从哪个表查询
|
||
* @param where 查询条件,如:{"uid":"ciniao"}
|
||
* @param order 排序条件,如:{"field":1}
|
||
* @param limit 指定行数:10
|
||
* @returns
|
||
*/
|
||
fmtOption(field?: string[], order?: any, limit?: number) {
|
||
let option = {};
|
||
|
||
if (field?.length > 0) {
|
||
option['projection'] = {};
|
||
for (let i = 0; i < field.length; i++) {
|
||
option['projection'][field[i]] = 1;
|
||
}
|
||
}
|
||
|
||
if (order != null) {
|
||
option['sort'] = order;
|
||
}
|
||
|
||
if (limit != null) {
|
||
option['limit'] = limit;
|
||
}
|
||
return option;
|
||
}
|
||
|
||
async find(from: string, where: any, field?: string[], order?: any, limit?: number) {
|
||
let option = this.fmtOption(field, order, limit);
|
||
return this.db.collection(from).find(where, option).toArray();
|
||
}
|
||
|
||
async findOne(from: string, where: any, field?: string[], order?: any, limit?: number) {
|
||
let option = this.fmtOption(field, order, limit);
|
||
return this.db.collection(from).findOne(where, option);
|
||
}
|
||
|
||
collection<T extends keyof MongodbCollections>(collection: T): Collection<OptionalId<MongodbCollections[T]>>;
|
||
collection<T extends keyof playerInfoType>(collection: 'playerInfo', type: T): Collection<OptionalId<CollectionPlayerInfo<T>>>;
|
||
collection(collection: string) {
|
||
return this.db.collection(collection);
|
||
}
|
||
|
||
cActionLog<T extends keyof actionLogType>(type: T): Collection<OptionalId<CollectionActionLog<T>>> {
|
||
return this.db.collection('actionLog');
|
||
}
|
||
|
||
cEvent<T extends keyof eventType>(type: T): Collection<OptionalId<CollectionEvent<T>>> {
|
||
return this.db.collection('event');
|
||
}
|
||
|
||
cPlayerInfo<T extends keyof playerInfoType>(type: T): Collection<OptionalId<CollectionPlayerInfo<T>>> {
|
||
return this.db.collection('playerInfo');
|
||
}
|
||
|
||
cRecord<T extends keyof recordType>(type: T): Collection<OptionalId<CollectionRecord<T>>> {
|
||
return this.db.collection('record');
|
||
}
|
||
|
||
/**_id转化 */
|
||
conversionId(_id: string): ObjectId;
|
||
conversionId(_id: ObjectId): string;
|
||
conversionId(_id: string | ObjectId) {
|
||
if (!_id) return null;
|
||
if (_id instanceof ObjectId) return _id.toHexString();
|
||
else return new ObjectId(_id);
|
||
}
|
||
|
||
/**_id数据转化 */
|
||
conversionIdObj<T extends { _id: string; }>(obj: T): Omit<T, '_id'> & { _id: ObjectId; };
|
||
conversionIdObj<T extends { _id: ObjectId; }>(obj: T): Omit<T, '_id'> & { _id: string; };
|
||
conversionIdObj(obj: { _id: string; } | { _id: ObjectId; }) {
|
||
if (!obj) return null;
|
||
let {_id, ...ops} = obj;
|
||
if (!_id) return ops;
|
||
return {
|
||
_id: this.conversionId(_id as any),
|
||
...ops
|
||
} as any;
|
||
}
|
||
|
||
createTreeObj(...args: { key: string, val: any; }[]);
|
||
createTreeObj(...args: { key: string, k: string, val: any; }[]);
|
||
createTreeObj(...args: { key: string, k: string, val: any; }[]) {
|
||
let obj = {};
|
||
args.forEach(v => {
|
||
if (Object.keys(v).length == 2) {
|
||
obj[v.key] = v.val;
|
||
} else {
|
||
obj[`${v.key}.${v.k}`] = v.val;
|
||
}
|
||
});
|
||
return obj;
|
||
}
|
||
|
||
// 增加查询索引(以达到检查数据库是否可用的目的)
|
||
indexInformation(name) {
|
||
return this.db.indexInformation(name)
|
||
}
|
||
} |