HJ_Server/src/setMongodb.ts

629 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}