const Provider = require('./Provider.js'); const { MongoClient } = require('mongodb'); class MongodbProvider extends Provider { constructor(manager, config) { super(manager, config); if(!config) throw new Error('No config file provided!'); if(config && (!config.database || !config.url)) throw new Error('Invalid config file provided!'); this.config = config; this.client; this.db; this.manager = manager; } async init() { this.manager.logger.log('Initializing mongodb.'); try { this.client = await MongoClient.connect(this.config.url+this.config.database, { useUnifiedTopology: true }); this.manager.db = await this.client.db(this.config.database); this.db = this.manager.db; // this.manager.logger.print('Database connected.'); } catch(err) { // this.manager.logger.error('Database connection failed!\n' + err); } return this; } /** * Find and return the first match * * @param {String} db The collection in which the data is to be updated * @param {Object} query The filter that is used to find the data * @returns {Array} An array containing the corresponding objects for the query * @memberof Database */ find(db, query) { //if(this.manager.debug) this.manager.logger.debug(`Incoming find query for ${db} with parameters ${JSON.stringify(query)}`); return new Promise((resolve, reject) => { this.db.collection(db).find(query, async (error, cursor) => { if(error) return reject(error); return resolve(await cursor.toArray()); }); }); } /** * Find and return the first match * * @param {String} db The collection in which the data is to be updated * @param {Object} query The filter that is used to find the data * @returns {Object} An object containing the queried data * @memberof Database */ findOne(db, query) { //if(this.manager.debug) this.manager.logger.debug(`Incoming findOne query for ${db} with parameters ${JSON.stringify(query)}`); return new Promise((resolve, reject) => { this.db.collection(db).findOne(query, async (error, item) => { if(error) return reject(error); return resolve(item); }); }); } /** * Update the first filter match. * * @param {String} db The collection in which the data is to be updated * @param {Object} filter The filter that is used to find the data * @param {Object} data The updated data * @param {Boolean} [upsert=false] Create a new entry if no match is found * @returns {WriteResult} Object containing the followint counts: Matched, Upserted, Modified * @memberof Database */ updateOne(db, query, data, upsert = false) { if(this.manager.debug) this.manager.logger.debug(`Incoming updateOne query for ${db} with parameters ${JSON.stringify(filter)}`); return new Promise((resolve, reject) => { this.db.collection(db).updateOne(query, { $set: data }, { upsert: upsert }, async (error, result) => { if(error) return reject(error); else { //return resolve(result) let { matchedCount, upsertedCount, modifiedCount } = result; return resolve({ matched: matchedCount, upserted: upsertedCount, modified: modifiedCount }); } }); }); } /** * Push data to an array * * @param {string} db The collection to query * @param {object} filter The filter to find the document to update * @param {object} data The data to be pushed * @param {boolean} [upsert=false] Create a new entry if no match is found * @returns * @memberof Database */ push(db, query, data, upsert = false) { //if(this.manager.debug) this.manager.logger.debug(`Incoming push query for ${db}, with upsert ${upsert} and with parameters ${JSON.stringify(filter)} and data ${JSON.stringify(data)}`); return new Promise((resolve, reject) => { this.db.collection(db).updateOne(query, { $push: data }, { upsert: upsert }, async (error, result) => { if(error) return reject(error); else return resolve(result); }); }); } /** * Find a random element from a database * * @param {string} db The collection to query * @param {object} [filter={}] The filtering object to narrow down the sample pool * @param {number} [amount=1] Amount of items to return * @returns {object} * @memberof Database */ random(db, query = {}, amount = 1) { //if(this.manager.debug) this.manager.logger.debug(`Incoming random query for ${db} with parameters ${JSON.stringify(filter)} and amount ${amount}`); if(amount > 100) amount = 100; return new Promise((resolve, reject)=>{ this.db.collection(db).aggregate([{ $match: query }, { $sample: {size: amount}}], function(err, item) { if(err) return reject(err); resolve(item); }); }); } } module.exports = MongodbProvider;