1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const Base = require('./Database');
|
7 | const mongodb = require('mongodb');
|
8 | const ObjectId = mongodb.ObjectID;
|
9 |
|
10 | module.exports = class MongoDatabase extends Base {
|
11 |
|
12 | static normalizeId (value) {
|
13 | return Array.isArray(value)
|
14 | ? value.map(this.normalizeObjectId, this)
|
15 | : this.normalizeObjectId(value);
|
16 | }
|
17 |
|
18 | static normalizeObjectId (value) {
|
19 | return value instanceof ObjectId ? value : ObjectId.isValid(value) ? ObjectId(value) : null;
|
20 | }
|
21 |
|
22 | constructor (config) {
|
23 | super({
|
24 | schema: 'mongodb',
|
25 | QueryBuilder: require('./MongoBuilder'),
|
26 | client: mongodb.MongoClient,
|
27 | ...config
|
28 | });
|
29 | this.settings.options = {
|
30 | bufferMaxEntries: 0,
|
31 | keepAlive: true,
|
32 | useNewUrlParser: true,
|
33 | useUnifiedTopology: true,
|
34 | ...this.settings.options
|
35 | };
|
36 | this._tableMap = {};
|
37 | }
|
38 |
|
39 | async openConnection () {
|
40 | this._client = await this.client.connect(this.getUri(true), this.settings.options);
|
41 | return this._client.db();
|
42 | }
|
43 |
|
44 | async closeConnection () {
|
45 | if (this._client) {
|
46 | await this._client.close(true);
|
47 | this._client = null;
|
48 | }
|
49 | }
|
50 |
|
51 | async isTableExists (name) {
|
52 | for (const {collectionName} of await this._connection.collections()) {
|
53 | if (name === collectionName) {
|
54 | return true;
|
55 | }
|
56 | }
|
57 | }
|
58 |
|
59 | async getTableNames () {
|
60 | const names = [];
|
61 | for (const {collectionName} of await this._connection.collections()) {
|
62 | names.push(collectionName);
|
63 | }
|
64 | return names;
|
65 | }
|
66 |
|
67 | getTable (name) {
|
68 | if (!this._tableMap[name]) {
|
69 | this._tableMap[name] = this._connection.collection(name);
|
70 | }
|
71 | return this._tableMap[name];
|
72 | }
|
73 |
|
74 |
|
75 |
|
76 | create (table) {
|
77 | this.logCommand('create', {table});
|
78 | return this._connection.createCollection(table);
|
79 | }
|
80 |
|
81 | find (table, query) {
|
82 | this.logCommand('find', {table, query});
|
83 | return this.getTable(table).find(query).toArray();
|
84 | }
|
85 |
|
86 | distinct (table, key, query, options) {
|
87 | this.logCommand('distinct', {table, query});
|
88 | return this.getTable(table).distinct(key, query, options);
|
89 | }
|
90 |
|
91 | async insert (table, data) {
|
92 | this.logCommand('insert', {table, data});
|
93 | if (Array.isArray(data)) {
|
94 | const result = await this.getTable(table).insertMany(data);
|
95 | return result.insertedIds;
|
96 | }
|
97 | const result = await this.getTable(table).insertOne(data);
|
98 | return result.insertedId;
|
99 | }
|
100 |
|
101 | upsert (table, query, data) {
|
102 | this.logCommand('upsert', {table, query, data});
|
103 | return this.getTable(table).updateOne(query, {$set: data}, {upsert: true});
|
104 | }
|
105 |
|
106 | update (table, query, data) {
|
107 | this.logCommand('update', {table, query, data});
|
108 | return this.getTable(table).updateOne(query, {$set: data});
|
109 | }
|
110 |
|
111 | updateAll (table, query, data) {
|
112 | this.logCommand('updateAll', {table, query, data});
|
113 | return this.getTable(table).updateMany(query, {$set: data});
|
114 | }
|
115 |
|
116 | updateAllPull (table, query, data) {
|
117 | this.logCommand('updateAllPull', {table, query, data});
|
118 | return this.getTable(table).updateMany(query, {$pull: data});
|
119 | }
|
120 |
|
121 | updateAllPush (table, query, data) {
|
122 | this.logCommand('updateAllPush', {table, query, data});
|
123 | return this.getTable(table).updateMany(query, {$push: data});
|
124 | }
|
125 |
|
126 | unset (table, query, data) {
|
127 | this.logCommand('unset', {table, query, data});
|
128 | return this.getTable(table).updateOne(query, {$unset: data});
|
129 | }
|
130 |
|
131 | unsetAll (table, query, data) {
|
132 | this.logCommand('unsetAll', {table, query, data});
|
133 | return this.getTable(table).updateMany(query, {$unset: data});
|
134 | }
|
135 |
|
136 | delete (table, query = {}) {
|
137 | this.logCommand('delete', {table, query});
|
138 | return this.getTable(table).deleteMany(query);
|
139 | }
|
140 |
|
141 | async drop (table) {
|
142 | if (await this.isTableExists(table)) {
|
143 | this.logCommand('drop', {table});
|
144 | return this.getTable(table).drop();
|
145 | }
|
146 | }
|
147 |
|
148 | async dropAll () {
|
149 | this.logCommand('dropAll');
|
150 | for (const name of await this.getTableNames()) {
|
151 | await this.drop(name);
|
152 | }
|
153 | }
|
154 |
|
155 | truncate (table) {
|
156 | return this.drop(table);
|
157 | }
|
158 |
|
159 | async rename (table, target) {
|
160 | if (await this.isTableExists(table)) {
|
161 | this.logCommand('rename', {table, target});
|
162 | return this._connection.renameCollection(...arguments);
|
163 | }
|
164 | }
|
165 |
|
166 |
|
167 |
|
168 | count (table, query) {
|
169 | this.logCommand('count', {table, query});
|
170 | return this.getTable(table).countDocuments(query);
|
171 | }
|
172 |
|
173 |
|
174 |
|
175 | async queryAll (query) {
|
176 | const cmd = await this.buildQuery(query);
|
177 | const cursor = this.getTable(cmd.from).find(cmd.where);
|
178 | if (cmd.select) {
|
179 | cursor.project(cmd.select);
|
180 | }
|
181 | if (cmd.order) {
|
182 | cursor.sort(cmd.order);
|
183 | }
|
184 | if (cmd.offset) {
|
185 | cursor.skip(cmd.offset);
|
186 | }
|
187 | if (cmd.limit) {
|
188 | cursor.limit(cmd.limit);
|
189 | }
|
190 | this.logCommand('find', cmd);
|
191 | let docs = await cursor.toArray();
|
192 | if (!cmd.order) {
|
193 | docs = query.sortOrderByKeys(docs);
|
194 | }
|
195 | return query.populate(docs);
|
196 | }
|
197 |
|
198 | async queryOne (query) {
|
199 | const docs = await this.queryAll(query.limit(1));
|
200 | return docs.length ? docs[0] : null;
|
201 | }
|
202 |
|
203 | async queryColumn (query, key) {
|
204 | const data = await this.queryAll(query.raw().select(key));
|
205 | if (Array.isArray(data)) {
|
206 | return data.map(doc => doc[key]);
|
207 | }
|
208 | for (const name of Object.keys(data)) {
|
209 | data[name] = data[name][key];
|
210 | }
|
211 | return data;
|
212 | }
|
213 |
|
214 | async queryDistinct (query, key) {
|
215 | const cmd = await this.buildQuery(query);
|
216 | return this.distinct(cmd.from, key, cmd.where, {});
|
217 | }
|
218 |
|
219 | async queryScalar (query, key) {
|
220 | const docs = await this.queryAll(query.raw().select(key).limit(1));
|
221 | return docs.length ? docs[0][key] : undefined;
|
222 | }
|
223 |
|
224 | async queryInsert (query, data) {
|
225 | const cmd = await this.buildQuery(query);
|
226 | return this.insert(cmd.from, data);
|
227 | }
|
228 |
|
229 | async queryUpdate (query, data) {
|
230 | const cmd = await this.buildQuery(query);
|
231 | return this.update(cmd.from, cmd.where, data);
|
232 | }
|
233 |
|
234 | async queryUpdateAll (query, data) {
|
235 | const cmd = await this.buildQuery(query);
|
236 | return this.updateAll(cmd.from, cmd.where, data);
|
237 | }
|
238 |
|
239 | async queryUpsert (query, data) {
|
240 | const cmd = await this.buildQuery(query);
|
241 | return this.upsert(cmd.from, cmd.where, data);
|
242 | }
|
243 |
|
244 | async queryDelete (query) {
|
245 | const cmd = await this.buildQuery(query);
|
246 | return this.delete(cmd.from, cmd.where);
|
247 | }
|
248 |
|
249 | async queryCount (query) {
|
250 | const cmd = await this.buildQuery(query);
|
251 | return this.count(cmd.from, cmd.where);
|
252 | }
|
253 |
|
254 |
|
255 |
|
256 | getIndexes (table, params = {full: true}) {
|
257 | return this.getTable(table).indexInformation(params);
|
258 | }
|
259 |
|
260 | |
261 |
|
262 |
|
263 |
|
264 | async createIndex (table, data) {
|
265 | await this.create(table);
|
266 | this.logCommand('createIndex', {table, data});
|
267 | return this.getTable(table).createIndex(...data);
|
268 | }
|
269 |
|
270 | async dropIndex (table, name) {
|
271 | if (await this.isTableExists(table)) {
|
272 | this.logCommand('dropIndex', {table, name});
|
273 | return this.getTable(table).dropIndex(name);
|
274 | }
|
275 | }
|
276 |
|
277 | async dropIndexes (table) {
|
278 | if (await this.isTableExists(table)) {
|
279 | this.logCommand('dropIndexes', {table});
|
280 | return this.getTable(table).dropIndexes();
|
281 | }
|
282 | }
|
283 |
|
284 | async reindex (table) {
|
285 | if (await this.isTableExists(table)) {
|
286 | this.logCommand('reindex', {table});
|
287 | return this.getTable(table).reIndex();
|
288 | }
|
289 | }
|
290 | };
|
291 | module.exports.init(); |
\ | No newline at end of file |