galactic-bot/structure/storage/interfaces/MongodbTable.js

191 lines
6.6 KiB
JavaScript

const { ObjectId } = require('mongodb');
class MongodbTable {
constructor(client, provider, opts = {}) {
this.client = client;
this.provider = provider;
this.name = opts.name;
}
//Data Search
find(query, opts = {}) { //opts: { projection: ... }
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.find(query, opts, async (error, cursor) => {
if(error) return reject(error);
return resolve(await cursor.toArray());
});
});
}
findOne(query, opts = {}) { //opts: { projection: ..., sort: ... }
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.findOne(query, opts, async (error, item) => {
if(error) return reject(error);
return resolve(item);
});
});
}
aggregate(query) {
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.aggregate(query, (error, item) => {
if(error) return reject(error);
return resolve(item.toArray());
});
});
}
random(query, amount = 1) {
query = this._handleData(query);
if(amount > 100) amount = 100;
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.aggregate([{ $match: query }, { $sample: { size: amount } }], (error, item) => {
if(error) return reject(error);
return resolve(item);
});
});
}
//Data Manipulation
insertOne(data) {
data = this._handleData(data);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.insertOne(data, (error, result) => {
if(error) return reject(error);
return resolve(result);
});
});
}
//NOTE: insertMany?
deleteOne(query) {
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.deleteOne(query, (error, result) => {
if(error) return reject(error);
return resolve(result);
});
});
}
deleteMany(query) {
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.deleteMany(query, (error, result) => {
if(error) return reject(error);
return resolve(result);
});
});
}
updateOne(query, data, upsert = true) {
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.updateOne(query, { $set: data }, { upsert }, async(error, result) => {
if(error) return reject(error);
const { matchedCount, upsertedCount, modifiedCount } = result;
return resolve({ matched: matchedCount, upserted: upsertedCount, modified: modifiedCount });
});
});
}
removeProperty(query, data) {
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
const unset = {};
for(const field of data) unset[field] = '';
this.collection.updateOne(query, { $unset: unset }, async (error, result) => {
if(error) return reject(error);
const { matchedCount, modifiedCount } = result;
return resolve({ matched: matchedCount, modified: modifiedCount });
});
});
}
push(query, data, upsert = true) {
query = this._handleData(query);
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.updateOne(query, { $push: data }, { upsert }, async(error, result) => {
if(error) return reject(error);
return resolve(result);
});
});
}
//Statistics
stats(options = {}) {
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.stats(options, (error, statistics) => {
if(error) return reject(error);
const { ns, size, count, avgObjSize, freeStorageSize, capped } = statistics;
return resolve({
index: ns,
averageSize: avgObjSize,
currentSize: size,
remainingSize: freeStorageSize,
maximumSize: size+freeStorageSize,
count,
capped
});
});
});
}
count(query, options = {}) {
return new Promise((resolve, reject) => {
if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.'));
this.collection.countDocuments(query, options, (error, result) => {
if(error) return reject(error);
return resolve(result);
});
});
}
//Lazy Function
_handleData(data) { //Convert data._id to Mongo ObjectIds (gets converted to plaintext through shard communication)
if(data._id) {
if(typeof data._id === 'string') data._id = ObjectId(data._id);
else if(typeof data._id === 'object') data._id = {
$in: Object.values(data._id)[0].map((id) => {
return ObjectId(id);
})
};
}
return data;
}
//Getters
get collection() {
return this.provider.db.collection(this.name);
}
}
module.exports = MongodbTable;