Implement unique incremebt
This commit is contained in:
		
							parent
							
								
									be2cde106b
								
							
						
					
					
						commit
						6cccd9d288
					
				
					 1 changed files with 74 additions and 30 deletions
				
			
		| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const nestedProperty = require('nested-property');
 | 
					const nestedProperty = require('nested-property');
 | 
				
			||||||
 | 
					import autobind from 'autobind-decorator';
 | 
				
			||||||
import * as mongo from 'mongodb';
 | 
					import * as mongo from 'mongodb';
 | 
				
			||||||
import db from '../db/mongodb';
 | 
					import db from '../db/mongodb';
 | 
				
			||||||
import { INote } from '../models/note';
 | 
					import { INote } from '../models/note';
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,11 @@ type ChartDocument<T extends Obj> = {
 | 
				
			||||||
	 * データ
 | 
						 * データ
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	data: T;
 | 
						data: T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * ユニークインクリメント用
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						unique?: Obj;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -61,7 +67,28 @@ abstract class Chart<T> {
 | 
				
			||||||
		this.collection.createIndex('group');
 | 
							this.collection.createIndex('group');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected async getCurrentStats(span: Span, group?: Obj): Promise<ChartDocument<T>> {
 | 
						@autobind
 | 
				
			||||||
 | 
						private convertQuery(x: Obj, path: string): Obj {
 | 
				
			||||||
 | 
							const query: Obj = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const dive = (x: Obj, path: string) => {
 | 
				
			||||||
 | 
								Object.entries(x).forEach(([k, v]) => {
 | 
				
			||||||
 | 
									const p = path ? `${path}.${k}` : k;
 | 
				
			||||||
 | 
									if (typeof v === 'number') {
 | 
				
			||||||
 | 
										query[p] = v;
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										dive(v, p);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							dive(x, path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return query;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
 | 
						private async getCurrentStats(span: Span, group?: Obj): Promise<ChartDocument<T>> {
 | 
				
			||||||
		const now = new Date();
 | 
							const now = new Date();
 | 
				
			||||||
		const y = now.getFullYear();
 | 
							const y = now.getFullYear();
 | 
				
			||||||
		const m = now.getMonth();
 | 
							const m = now.getMonth();
 | 
				
			||||||
| 
						 | 
					@ -129,39 +156,42 @@ abstract class Chart<T> {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected inc(inc: Partial<T>, group?: Obj): void {
 | 
						@autobind
 | 
				
			||||||
		const query: Obj = {};
 | 
						protected commit(query: Obj, group?: Obj, uniqueKey?: string, uniqueValue?: string): void {
 | 
				
			||||||
 | 
							const update = (stats: ChartDocument<T>) => {
 | 
				
			||||||
 | 
								// ユニークインクリメントの場合、指定のキーに指定の値が既に存在していたら弾く
 | 
				
			||||||
 | 
								if (uniqueKey && stats.unique && stats.unique[uniqueKey] && stats.unique[uniqueKey].includes(uniqueValue)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const dive = (x: Obj, path?: string) => {
 | 
								if (uniqueKey) {
 | 
				
			||||||
			Object.entries(x).forEach(([k, v]) => {
 | 
									query['$push'] = {
 | 
				
			||||||
				const p = path ? `${path}.${k}` : k;
 | 
										[`unique.${uniqueKey}`]: uniqueValue
 | 
				
			||||||
				if (typeof v === 'number') {
 | 
									};
 | 
				
			||||||
					query[`data.${p}`] = v;
 | 
								}
 | 
				
			||||||
				} else {
 | 
					
 | 
				
			||||||
					dive(v, p);
 | 
								this.collection.update({
 | 
				
			||||||
				}
 | 
									_id: stats._id
 | 
				
			||||||
			});
 | 
								}, query);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dive(inc);
 | 
							this.getCurrentStats('day', group).then(stats => update(stats));
 | 
				
			||||||
 | 
							this.getCurrentStats('hour', group).then(stats => update(stats));
 | 
				
			||||||
		this.getCurrentStats('day', group).then(stats => {
 | 
					 | 
				
			||||||
			this.collection.findOneAndUpdate({
 | 
					 | 
				
			||||||
				_id: stats._id
 | 
					 | 
				
			||||||
			}, {
 | 
					 | 
				
			||||||
				$inc: query
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.getCurrentStats('hour', group).then(stats => {
 | 
					 | 
				
			||||||
			this.collection.findOneAndUpdate({
 | 
					 | 
				
			||||||
				_id: stats._id
 | 
					 | 
				
			||||||
			}, {
 | 
					 | 
				
			||||||
				$inc: query
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
 | 
						protected inc(inc: Partial<T>, group?: Obj): void {
 | 
				
			||||||
 | 
							this.commit({
 | 
				
			||||||
 | 
								$inc: this.convertQuery(inc, 'data')
 | 
				
			||||||
 | 
							}, group);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
 | 
						protected incIfUnique(inc: Partial<T>, key: string, value: string, group?: Obj): void {
 | 
				
			||||||
 | 
							this.commit({
 | 
				
			||||||
 | 
								$inc: this.convertQuery(inc, 'data')
 | 
				
			||||||
 | 
							}, group, key, value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	public async getStats(span: Span, range: number, group?: Obj): Promise<ArrayValue<T>> {
 | 
						public async getStats(span: Span, range: number, group?: Obj): Promise<ArrayValue<T>> {
 | 
				
			||||||
		const chart: T[] = [];
 | 
							const chart: T[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -296,6 +326,7 @@ class UsersChart extends Chart<UsersStats> {
 | 
				
			||||||
		super('usersStats');
 | 
							super('usersStats');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateInitialStats(): UsersStats {
 | 
						protected generateInitialStats(): UsersStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			local: {
 | 
								local: {
 | 
				
			||||||
| 
						 | 
					@ -311,6 +342,7 @@ class UsersChart extends Chart<UsersStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateEmptyStats(mostRecentStats: UsersStats): UsersStats {
 | 
						protected generateEmptyStats(mostRecentStats: UsersStats): UsersStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			local: {
 | 
								local: {
 | 
				
			||||||
| 
						 | 
					@ -326,6 +358,7 @@ class UsersChart extends Chart<UsersStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	public async update(user: IUser, isAdditional: boolean) {
 | 
						public async update(user: IUser, isAdditional: boolean) {
 | 
				
			||||||
		const update: Obj = {};
 | 
							const update: Obj = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,6 +457,7 @@ class NotesChart extends Chart<NotesStats> {
 | 
				
			||||||
		super('notesStats');
 | 
							super('notesStats');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateInitialStats(): NotesStats {
 | 
						protected generateInitialStats(): NotesStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			local: {
 | 
								local: {
 | 
				
			||||||
| 
						 | 
					@ -449,6 +483,7 @@ class NotesChart extends Chart<NotesStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateEmptyStats(mostRecentStats: NotesStats): NotesStats {
 | 
						protected generateEmptyStats(mostRecentStats: NotesStats): NotesStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			local: {
 | 
								local: {
 | 
				
			||||||
| 
						 | 
					@ -474,8 +509,11 @@ class NotesChart extends Chart<NotesStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	public async update(note: INote, isAdditional: boolean) {
 | 
						public async update(note: INote, isAdditional: boolean) {
 | 
				
			||||||
		const update: Obj = {};
 | 
							const update: Obj = {
 | 
				
			||||||
 | 
								diffs: {}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		update.total = isAdditional ? 1 : -1;
 | 
							update.total = isAdditional ? 1 : -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -577,6 +615,7 @@ class DriveChart extends Chart<DriveStats> {
 | 
				
			||||||
		super('driveStats');
 | 
							super('driveStats');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateInitialStats(): DriveStats {
 | 
						protected generateInitialStats(): DriveStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			local: {
 | 
								local: {
 | 
				
			||||||
| 
						 | 
					@ -598,6 +637,7 @@ class DriveChart extends Chart<DriveStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateEmptyStats(mostRecentStats: DriveStats): DriveStats {
 | 
						protected generateEmptyStats(mostRecentStats: DriveStats): DriveStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			local: {
 | 
								local: {
 | 
				
			||||||
| 
						 | 
					@ -619,6 +659,7 @@ class DriveChart extends Chart<DriveStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	public async update(file: IDriveFile, isAdditional: boolean) {
 | 
						public async update(file: IDriveFile, isAdditional: boolean) {
 | 
				
			||||||
		const update: Obj = {};
 | 
							const update: Obj = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -678,6 +719,7 @@ class NetworkChart extends Chart<NetworkStats> {
 | 
				
			||||||
		super('networkStats');
 | 
							super('networkStats');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateInitialStats(): NetworkStats {
 | 
						protected generateInitialStats(): NetworkStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			incomingRequests: 0,
 | 
								incomingRequests: 0,
 | 
				
			||||||
| 
						 | 
					@ -688,6 +730,7 @@ class NetworkChart extends Chart<NetworkStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	protected generateEmptyStats(mostRecentStats: NetworkStats): NetworkStats {
 | 
						protected generateEmptyStats(mostRecentStats: NetworkStats): NetworkStats {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			incomingRequests: 0,
 | 
								incomingRequests: 0,
 | 
				
			||||||
| 
						 | 
					@ -698,6 +741,7 @@ class NetworkChart extends Chart<NetworkStats> {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@autobind
 | 
				
			||||||
	public async update(incomingRequests: number, time: number, incomingBytes: number, outgoingBytes: number) {
 | 
						public async update(incomingRequests: number, time: number, incomingBytes: number, outgoingBytes: number) {
 | 
				
			||||||
		const inc: Partial<NetworkStats> = {
 | 
							const inc: Partial<NetworkStats> = {
 | 
				
			||||||
			incomingRequests: incomingRequests,
 | 
								incomingRequests: incomingRequests,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue