HJ_Server/src/setMongodb.ts
2023-12-27 21:05:53 +08:00

672 lines
16 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,
FindCursor,
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';
import { addGameLog } from './gameLog';
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}
},
{
key: {type: 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}
},
],
huodong_user: [
{
key: {uid: 1}, unique: true,
}
],
};
export async function initMongoDB() {
//mongodb连接数说明https://blog.csdn.net/for_cxc/article/details/116859714
//可结合查看node_modules\mongodb\lib\connection_string.js
//maxPoolSize默认值100
/**
* MongoDB连接池具有多个参数用于控制连接池的行为和性能。下面是一些常用的连接池参数及其作用
* maxPoolSize连接池的最大连接数。默认值为100。该参数决定了连接池中可以同时存在的最大连接数超过这个数量后新的连接请求会被阻塞。
* minPoolSize连接池的最小连接数。默认值为0。该参数决定了连接池中保持的最小连接数当连接数少于这个数量时连接池会自动创建新的连接实例。
* maxIdleTimeMS连接的最大空闲时间毫秒。默认值为0表示连接不会被强制断开。该参数决定了连接在空闲一定时间后是否被断开以释放服务器资源。
* waitQueueTimeoutMS连接请求的等待时间毫秒。默认值为0表示无限等待。当连接池达到最大连接数时新的连接请求会被放入等待队列中该参数决定了连接请求在队列中的最长等待时间。
*/
let option:MongoClientOptions = {
//空闲5分钟后关闭
maxIdleTimeMS: 5*60*1000
};
//跨服只有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,
maxIdleTimeMS: 5*60*1000
});
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)
}
}
// //@ts-ignore
// FindCursor.prototype._toArray = FindCursor.prototype.toArray;
// //@ts-ignore
// FindCursor.prototype.toArray = async function(){
// let rss = await this._toArray();
//
// //如果返回的数据超过50条
// if(rss.length>50){
// addGameLog("system","findCount",null,{
// collection: this.namespace.collection,
// db:this.namespace.db,
// count:rss.length
// })
// console.log("system,findCount",{
// collection: this.namespace.collection,
// db:this.namespace.db,
// count:rss.length
// })
// console.trace();
// }
// return rss;
// }