Page MenuHomeSealhub

datastore.ts
No OneTemporary

datastore.ts

import { MongoClient, Db, Collection as MongoCollection } from "mongodb";
import { App } from "../main";
import Collection from "../chip-types/collection";
import merge from "deepmerge";
import { QueryStage } from "./query";
export type OutputOptions = { sort?: any; skip?: number; amount?: number };
export default class Datastore {
app: App;
client: MongoClient;
db: Db;
constructor(app: App) {
this.app = app;
}
async start() {
const config = this.app.ConfigManager.get("datastore_mongo") as {
host: string;
port: number;
db_name: string;
};
const url = `mongodb://${config.host}:${config.port}/${config.db_name}`;
this.client = await MongoClient.connect(url, { useNewUrlParser: true });
if (!this.client) {
return Promise.reject(
"MongoDB was not found, please make sure it's installed. Check https://docs.mongodb.org/manual/tutorial/ for more info."
);
}
this.db = this.client.db(config.db_name);
return this.post_start();
}
async post_start() {
const collection_names = this.app.ChipManager.getAllCollections();
const collections = collection_names.map((name) =>
this.app.ChipManager.getChip("collection", name)
);
for (let collection of collections) {
await this.create_index(collection);
}
}
async create_index(collection: Collection) {
let indexes: [string, any][] = [["sealious_id", 1]];
for (const field_name in collection.fields) {
indexes.push([
field_name,
collection.fields[field_name].hasIndex(),
]);
}
const db_collection = this.db.collection(collection.name);
const all_indexes = indexes
.filter((e) => e[1] !== false)
.map((index) => {
if (index[1] instanceof Object) {
const ret = [];
for (const i in index[1]) {
ret.push([index[0] + "." + i, index[1][i]]);
}
return ret;
}
return [index];
})
.reduce((a, b) => a.concat(b), []);
const non_text_indexes = all_indexes
.filter((e) => e[1] !== "text")
.map((e) => {
return { [e[0]]: e[1] };
});
// if multiple fields take part in full text search, we need to combine them into a single index.
let text_indexes = [
all_indexes
.filter((e) => e[1] === "text")
.reduce((a, b) => merge(a, { [b[0]]: b[1] })),
];
if (Object.keys(text_indexes[0]).length == 0) {
text_indexes = [];
}
const merged_indexes = text_indexes.concat(non_text_indexes);
for (const index of merged_indexes) {
await createIndex(db_collection, index).catch(
async (error: Error & { code?: number; message: string }) => {
if (error && error.code === 85) {
const index_name = (error.message.match(
/name: \"([^\"]+)\"/g
) as string[])[1]
.replace('name: "', "")
.replace('"', "");
await db_collection.dropIndex(index_name);
return createIndex(db_collection, index);
}
throw error;
}
);
}
}
find(
collection_name: string,
query: any,
options: Parameters<MongoCollection["find"]>[1] = {},
output_options: OutputOptions = {}
) {
const cursor = this.db.collection(collection_name).find(query, options);
if (output_options.sort) {
cursor.sort(output_options.sort);
}
if (output_options.skip) {
cursor.skip(output_options.skip);
}
if (output_options.amount) {
cursor.limit(output_options.amount);
}
return cursor.toArray();
}
aggregate(
collection_name: string,
pipeline: QueryStage[],
_ = {},
output_options: OutputOptions = {}
) {
const cursor = this.db.collection(collection_name).aggregate(pipeline);
if (output_options.sort) {
cursor.sort(output_options.sort);
}
if (output_options.skip) {
cursor.skip(output_options.skip);
}
if (output_options.amount) {
cursor.limit(output_options.amount);
}
return cursor.toArray();
}
async insert(
collection_name: string,
to_insert: any,
options: Parameters<MongoCollection["insertOne"]>[1]
) {
const result = await this.db
.collection(collection_name)
.insertOne(to_insert, options);
return result.ops[0];
}
update(collection_name: string, query: any, new_value: any) {
query = process_query(query);
return this.db.collection(collection_name).updateOne(query, new_value);
}
remove(collection_name: string, query: any, just_one: boolean) {
query = process_query(query);
const method = just_one ? "deleteOne" : "deleteMany";
return this.db.collection(collection_name)[method](query);
}
createIndex(
collection_name: string,
index: any,
options: Parameters<MongoCollection["createIndex"]>[1]
) {
const collection = this.db.collection(collection_name);
return collection.createIndex(index, options);
}
stop() {
this.client.close();
}
}
function process_query(query: any) {
if (!query) {
return {};
}
const new_query: { [key: string]: any } = {};
for (const attribute_name in query) {
if (attribute_name == "sealious_id") {
new_query[attribute_name] = query[attribute_name];
continue;
}
if (query[attribute_name] instanceof Object) {
if (attribute_name[0] === "$") {
new_query[attribute_name] = query[attribute_name];
} else {
for (const i in query[attribute_name]) {
new_query[attribute_name + "." + i] =
query[attribute_name][i];
}
}
} else {
new_query[attribute_name] = query[attribute_name];
}
}
return new_query;
}
function createIndex(
db_collection: MongoCollection,
index: Parameters<MongoCollection["createIndex"]>[0]
) {
return db_collection.createIndex(index, { background: true });
}

File Metadata

Mime Type
text/x-java
Expires
Fri, Jan 24, 15:15 (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
601483
Default Alt Text
datastore.ts (5 KB)

Event Timeline