meadow 2.0.23 → 2.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -141
- package/docs/README.md +34 -230
- package/docs/_cover.md +14 -0
- package/docs/_sidebar.md +44 -12
- package/docs/_topbar.md +5 -0
- package/docs/api/doCount.md +109 -0
- package/docs/api/doCreate.md +132 -0
- package/docs/api/doDelete.md +101 -0
- package/docs/api/doRead.md +122 -0
- package/docs/api/doReads.md +136 -0
- package/docs/api/doUndelete.md +98 -0
- package/docs/api/doUpdate.md +129 -0
- package/docs/api/getRoleName.md +84 -0
- package/docs/api/loadFromPackage.md +153 -0
- package/docs/api/marshalRecordFromSourceToObject.md +92 -0
- package/docs/api/query.md +133 -0
- package/docs/api/rawQueries.md +197 -0
- package/docs/api/reference.md +117 -0
- package/docs/api/setAuthorizer.md +103 -0
- package/docs/api/setDefault.md +90 -0
- package/docs/api/setDefaultIdentifier.md +84 -0
- package/docs/api/setDomain.md +56 -0
- package/docs/api/setIDUser.md +91 -0
- package/docs/api/setJsonSchema.md +92 -0
- package/docs/api/setProvider.md +87 -0
- package/docs/api/setSchema.md +107 -0
- package/docs/api/setScope.md +68 -0
- package/docs/api/validateObject.md +119 -0
- package/docs/architecture.md +316 -0
- package/docs/audit-tracking.md +226 -0
- package/docs/configuration.md +317 -0
- package/docs/providers/meadow-endpoints.md +306 -0
- package/docs/providers/mongodb.md +319 -0
- package/docs/providers/postgresql.md +312 -0
- package/docs/providers/rocksdb.md +297 -0
- package/docs/query-dsl.md +269 -0
- package/docs/quick-start.md +384 -0
- package/docs/raw-queries.md +193 -0
- package/docs/retold-catalog.json +61 -1
- package/docs/retold-keyword-index.json +15860 -4839
- package/docs/soft-deletes.md +224 -0
- package/package.json +44 -13
- package/scripts/bookstore-seed-postgresql.sql +135 -0
- package/scripts/dgraph-test-db.sh +144 -0
- package/scripts/meadow-test-cleanup.sh +5 -1
- package/scripts/mongodb-test-db.sh +98 -0
- package/scripts/postgresql-test-db.sh +124 -0
- package/scripts/solr-test-db.sh +135 -0
- package/source/Meadow.js +5 -0
- package/source/providers/Meadow-Provider-DGraph.js +679 -0
- package/source/providers/Meadow-Provider-MeadowEndpoints.js +1 -1
- package/source/providers/Meadow-Provider-MongoDB.js +527 -0
- package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
- package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
- package/source/providers/Meadow-Provider-Solr.js +726 -0
- package/test/Meadow-Provider-DGraph_tests.js +741 -0
- package/test/Meadow-Provider-MongoDB_tests.js +661 -0
- package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
- package/test/Meadow-Provider-RocksDB_tests.js +887 -0
- package/test/Meadow-Provider-SQLiteBrowser-Headless_tests.js +657 -0
- package/test/Meadow-Provider-SQLiteBrowser_tests.js +895 -0
- package/test/Meadow-Provider-Solr_tests.js +679 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
// ##### Part of the **[retold](https://stevenvelozo.github.io/retold/)** system
|
|
2
|
+
/**
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @author <steven@velozo.com>
|
|
5
|
+
*/
|
|
6
|
+
var MeadowProvider = function ()
|
|
7
|
+
{
|
|
8
|
+
function createNew(pFable)
|
|
9
|
+
{
|
|
10
|
+
// If a valid Fable object isn't passed in, return a constructor
|
|
11
|
+
if (typeof (pFable) !== 'object')
|
|
12
|
+
{
|
|
13
|
+
return { new: createNew };
|
|
14
|
+
}
|
|
15
|
+
var _Fable = pFable;
|
|
16
|
+
var _GlobalLogLevel = 0;
|
|
17
|
+
if (_Fable.settings.MongoDB)
|
|
18
|
+
{
|
|
19
|
+
_GlobalLogLevel = _Fable.settings.MongoDB.GlobalLogLevel || 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the MongoDB Db instance from the connection service.
|
|
24
|
+
*/
|
|
25
|
+
var getDB = function ()
|
|
26
|
+
{
|
|
27
|
+
if (typeof (_Fable.MeadowMongoDBProvider) == 'object' && _Fable.MeadowMongoDBProvider.connected)
|
|
28
|
+
{
|
|
29
|
+
return _Fable.MeadowMongoDBProvider.pool;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
var getProvider = function ()
|
|
35
|
+
{
|
|
36
|
+
if (typeof (_Fable.MeadowMongoDBProvider) == 'object')
|
|
37
|
+
{
|
|
38
|
+
return _Fable.MeadowMongoDBProvider;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Deep-walk an object and replace $$NOW sentinels with new Date().
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} pObj Object to process (mutated in place)
|
|
47
|
+
* @return {Object} The same object with sentinels replaced
|
|
48
|
+
*/
|
|
49
|
+
var replaceSentinels = function (pObj)
|
|
50
|
+
{
|
|
51
|
+
if (typeof pObj !== 'object' || pObj === null)
|
|
52
|
+
{
|
|
53
|
+
return pObj;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (var tmpKey in pObj)
|
|
57
|
+
{
|
|
58
|
+
if (!pObj.hasOwnProperty(tmpKey))
|
|
59
|
+
{
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (pObj[tmpKey] === '$$NOW')
|
|
64
|
+
{
|
|
65
|
+
pObj[tmpKey] = new Date();
|
|
66
|
+
}
|
|
67
|
+
else if (typeof pObj[tmpKey] === 'object' && pObj[tmpKey] !== null)
|
|
68
|
+
{
|
|
69
|
+
replaceSentinels(pObj[tmpKey]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return pObj;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get the next auto-increment sequence value for a collection/column pair.
|
|
77
|
+
* Uses the _meadow_counters collection with atomic findOneAndUpdate.
|
|
78
|
+
*
|
|
79
|
+
* @param {Object} pDB MongoDB Db instance
|
|
80
|
+
* @param {String} pScope Collection name
|
|
81
|
+
* @param {String} pIDColumn Identity column name
|
|
82
|
+
* @param {Function} fCallback (error, nextSequenceValue)
|
|
83
|
+
*/
|
|
84
|
+
var getNextSequence = function (pDB, pScope, pIDColumn, fCallback)
|
|
85
|
+
{
|
|
86
|
+
var tmpCounterKey = pScope + '.' + pIDColumn;
|
|
87
|
+
pDB.collection('_meadow_counters').findOneAndUpdate(
|
|
88
|
+
{ _id: tmpCounterKey },
|
|
89
|
+
{ $inc: { seq: 1 } },
|
|
90
|
+
{ upsert: true, returnDocument: 'after' }
|
|
91
|
+
)
|
|
92
|
+
.then(function (pResult)
|
|
93
|
+
{
|
|
94
|
+
return fCallback(null, pResult.seq);
|
|
95
|
+
})
|
|
96
|
+
.catch(function (pError)
|
|
97
|
+
{
|
|
98
|
+
return fCallback(pError);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// The Meadow marshaller also passes in the Schema as the third parameter
|
|
103
|
+
var marshalRecordFromSourceToObject = function (pObject, pRecord)
|
|
104
|
+
{
|
|
105
|
+
for (var tmpColumn in pRecord)
|
|
106
|
+
{
|
|
107
|
+
// Skip MongoDB's internal _id field
|
|
108
|
+
if (tmpColumn === '_id')
|
|
109
|
+
{
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
pObject[tmpColumn] = pRecord[tmpColumn];
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
var Create = function (pQuery, fCallback)
|
|
117
|
+
{
|
|
118
|
+
var tmpResult = pQuery.parameters.result;
|
|
119
|
+
|
|
120
|
+
pQuery.setDialect('MongoDB').buildCreateQuery();
|
|
121
|
+
|
|
122
|
+
if (pQuery.logLevel > 0 ||
|
|
123
|
+
_GlobalLogLevel > 0)
|
|
124
|
+
{
|
|
125
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
var tmpDB = getDB();
|
|
129
|
+
if (!tmpDB)
|
|
130
|
+
{
|
|
131
|
+
tmpResult.error = new Error('No MongoDB connection available.');
|
|
132
|
+
tmpResult.executed = true;
|
|
133
|
+
return fCallback();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
var tmpOp = pQuery.query.parameters.mongoOperation;
|
|
137
|
+
if (!tmpOp)
|
|
138
|
+
{
|
|
139
|
+
tmpResult.error = new Error('No MongoDB operation generated.');
|
|
140
|
+
tmpResult.executed = true;
|
|
141
|
+
return fCallback();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
var tmpCollection = tmpDB.collection(tmpOp.collection);
|
|
145
|
+
var tmpDocument = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.document)));
|
|
146
|
+
|
|
147
|
+
// Check for $$AUTOINCREMENT sentinel
|
|
148
|
+
var tmpAutoIncrementColumn = false;
|
|
149
|
+
for (var tmpKey in tmpDocument)
|
|
150
|
+
{
|
|
151
|
+
if (tmpDocument[tmpKey] === '$$AUTOINCREMENT')
|
|
152
|
+
{
|
|
153
|
+
tmpAutoIncrementColumn = tmpKey;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (tmpAutoIncrementColumn)
|
|
159
|
+
{
|
|
160
|
+
// Get next sequence, then insert
|
|
161
|
+
getNextSequence(tmpDB, tmpOp.collection, tmpAutoIncrementColumn, function (pSeqError, pSeqValue)
|
|
162
|
+
{
|
|
163
|
+
if (pSeqError)
|
|
164
|
+
{
|
|
165
|
+
tmpResult.error = pSeqError;
|
|
166
|
+
tmpResult.value = false;
|
|
167
|
+
tmpResult.executed = true;
|
|
168
|
+
return fCallback();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
tmpDocument[tmpAutoIncrementColumn] = pSeqValue;
|
|
172
|
+
|
|
173
|
+
tmpCollection.insertOne(tmpDocument)
|
|
174
|
+
.then(function (pInsertResult)
|
|
175
|
+
{
|
|
176
|
+
tmpResult.error = null;
|
|
177
|
+
tmpResult.value = pSeqValue;
|
|
178
|
+
tmpResult.executed = true;
|
|
179
|
+
return fCallback();
|
|
180
|
+
})
|
|
181
|
+
.catch(function (pError)
|
|
182
|
+
{
|
|
183
|
+
tmpResult.error = pError;
|
|
184
|
+
tmpResult.value = false;
|
|
185
|
+
tmpResult.executed = true;
|
|
186
|
+
return fCallback();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
else
|
|
191
|
+
{
|
|
192
|
+
tmpCollection.insertOne(tmpDocument)
|
|
193
|
+
.then(function (pInsertResult)
|
|
194
|
+
{
|
|
195
|
+
tmpResult.error = null;
|
|
196
|
+
tmpResult.value = pInsertResult.insertedId;
|
|
197
|
+
tmpResult.executed = true;
|
|
198
|
+
return fCallback();
|
|
199
|
+
})
|
|
200
|
+
.catch(function (pError)
|
|
201
|
+
{
|
|
202
|
+
tmpResult.error = pError;
|
|
203
|
+
tmpResult.value = false;
|
|
204
|
+
tmpResult.executed = true;
|
|
205
|
+
return fCallback();
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
var Read = function (pQuery, fCallback)
|
|
211
|
+
{
|
|
212
|
+
var tmpResult = pQuery.parameters.result;
|
|
213
|
+
|
|
214
|
+
pQuery.setDialect('MongoDB').buildReadQuery();
|
|
215
|
+
|
|
216
|
+
if (pQuery.logLevel > 0 ||
|
|
217
|
+
_GlobalLogLevel > 0)
|
|
218
|
+
{
|
|
219
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
var tmpDB = getDB();
|
|
223
|
+
if (!tmpDB)
|
|
224
|
+
{
|
|
225
|
+
tmpResult.error = new Error('No MongoDB connection available.');
|
|
226
|
+
tmpResult.executed = true;
|
|
227
|
+
return fCallback();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
var tmpOp = pQuery.query.parameters.mongoOperation;
|
|
231
|
+
var tmpCollection = tmpDB.collection(tmpOp.collection);
|
|
232
|
+
|
|
233
|
+
var tmpOptions = {};
|
|
234
|
+
if (tmpOp.projection && Object.keys(tmpOp.projection).length > 0)
|
|
235
|
+
{
|
|
236
|
+
tmpOptions.projection = tmpOp.projection;
|
|
237
|
+
}
|
|
238
|
+
if (tmpOp.sort && Object.keys(tmpOp.sort).length > 0)
|
|
239
|
+
{
|
|
240
|
+
tmpOptions.sort = tmpOp.sort;
|
|
241
|
+
}
|
|
242
|
+
if (tmpOp.skip)
|
|
243
|
+
{
|
|
244
|
+
tmpOptions.skip = tmpOp.skip;
|
|
245
|
+
}
|
|
246
|
+
if (tmpOp.limit)
|
|
247
|
+
{
|
|
248
|
+
tmpOptions.limit = tmpOp.limit;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
tmpCollection.find(tmpOp.filter, tmpOptions).toArray()
|
|
252
|
+
.then(function (pDocs)
|
|
253
|
+
{
|
|
254
|
+
tmpResult.error = null;
|
|
255
|
+
tmpResult.value = pDocs;
|
|
256
|
+
tmpResult.executed = true;
|
|
257
|
+
return fCallback();
|
|
258
|
+
})
|
|
259
|
+
.catch(function (pError)
|
|
260
|
+
{
|
|
261
|
+
tmpResult.error = pError;
|
|
262
|
+
tmpResult.value = false;
|
|
263
|
+
tmpResult.executed = true;
|
|
264
|
+
return fCallback();
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
var Update = function (pQuery, fCallback)
|
|
269
|
+
{
|
|
270
|
+
var tmpResult = pQuery.parameters.result;
|
|
271
|
+
|
|
272
|
+
pQuery.setDialect('MongoDB').buildUpdateQuery();
|
|
273
|
+
|
|
274
|
+
if (pQuery.logLevel > 0 ||
|
|
275
|
+
_GlobalLogLevel > 0)
|
|
276
|
+
{
|
|
277
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
var tmpDB = getDB();
|
|
281
|
+
if (!tmpDB)
|
|
282
|
+
{
|
|
283
|
+
tmpResult.error = new Error('No MongoDB connection available.');
|
|
284
|
+
tmpResult.executed = true;
|
|
285
|
+
return fCallback();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
var tmpOp = pQuery.query.parameters.mongoOperation;
|
|
289
|
+
if (!tmpOp)
|
|
290
|
+
{
|
|
291
|
+
tmpResult.error = new Error('No MongoDB operation generated.');
|
|
292
|
+
tmpResult.executed = true;
|
|
293
|
+
return fCallback();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
var tmpCollection = tmpDB.collection(tmpOp.collection);
|
|
297
|
+
var tmpUpdate = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.update)));
|
|
298
|
+
|
|
299
|
+
tmpCollection.updateMany(tmpOp.filter, tmpUpdate)
|
|
300
|
+
.then(function (pUpdateResult)
|
|
301
|
+
{
|
|
302
|
+
tmpResult.error = null;
|
|
303
|
+
tmpResult.value = pUpdateResult;
|
|
304
|
+
tmpResult.executed = true;
|
|
305
|
+
return fCallback();
|
|
306
|
+
})
|
|
307
|
+
.catch(function (pError)
|
|
308
|
+
{
|
|
309
|
+
tmpResult.error = pError;
|
|
310
|
+
tmpResult.value = false;
|
|
311
|
+
tmpResult.executed = true;
|
|
312
|
+
return fCallback();
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
var Delete = function (pQuery, fCallback)
|
|
317
|
+
{
|
|
318
|
+
var tmpResult = pQuery.parameters.result;
|
|
319
|
+
|
|
320
|
+
pQuery.setDialect('MongoDB').buildDeleteQuery();
|
|
321
|
+
|
|
322
|
+
if (pQuery.logLevel > 0 ||
|
|
323
|
+
_GlobalLogLevel > 0)
|
|
324
|
+
{
|
|
325
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
var tmpDB = getDB();
|
|
329
|
+
if (!tmpDB)
|
|
330
|
+
{
|
|
331
|
+
tmpResult.error = new Error('No MongoDB connection available.');
|
|
332
|
+
tmpResult.executed = true;
|
|
333
|
+
return fCallback();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
var tmpOp = pQuery.query.parameters.mongoOperation;
|
|
337
|
+
var tmpCollection = tmpDB.collection(tmpOp.collection);
|
|
338
|
+
|
|
339
|
+
if (tmpOp.operation === 'updateMany')
|
|
340
|
+
{
|
|
341
|
+
// Soft delete
|
|
342
|
+
var tmpUpdate = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.update)));
|
|
343
|
+
tmpCollection.updateMany(tmpOp.filter, tmpUpdate)
|
|
344
|
+
.then(function (pUpdateResult)
|
|
345
|
+
{
|
|
346
|
+
tmpResult.error = null;
|
|
347
|
+
tmpResult.value = pUpdateResult.modifiedCount;
|
|
348
|
+
tmpResult.executed = true;
|
|
349
|
+
return fCallback();
|
|
350
|
+
})
|
|
351
|
+
.catch(function (pError)
|
|
352
|
+
{
|
|
353
|
+
tmpResult.error = pError;
|
|
354
|
+
tmpResult.value = false;
|
|
355
|
+
tmpResult.executed = true;
|
|
356
|
+
return fCallback();
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
else
|
|
360
|
+
{
|
|
361
|
+
// Hard delete
|
|
362
|
+
tmpCollection.deleteMany(tmpOp.filter)
|
|
363
|
+
.then(function (pDeleteResult)
|
|
364
|
+
{
|
|
365
|
+
tmpResult.error = null;
|
|
366
|
+
tmpResult.value = pDeleteResult.deletedCount;
|
|
367
|
+
tmpResult.executed = true;
|
|
368
|
+
return fCallback();
|
|
369
|
+
})
|
|
370
|
+
.catch(function (pError)
|
|
371
|
+
{
|
|
372
|
+
tmpResult.error = pError;
|
|
373
|
+
tmpResult.value = false;
|
|
374
|
+
tmpResult.executed = true;
|
|
375
|
+
return fCallback();
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
var Undelete = function (pQuery, fCallback)
|
|
381
|
+
{
|
|
382
|
+
var tmpResult = pQuery.parameters.result;
|
|
383
|
+
|
|
384
|
+
pQuery.setDialect('MongoDB').buildUndeleteQuery();
|
|
385
|
+
|
|
386
|
+
if (pQuery.logLevel > 0 ||
|
|
387
|
+
_GlobalLogLevel > 0)
|
|
388
|
+
{
|
|
389
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
var tmpDB = getDB();
|
|
393
|
+
if (!tmpDB)
|
|
394
|
+
{
|
|
395
|
+
tmpResult.error = new Error('No MongoDB connection available.');
|
|
396
|
+
tmpResult.executed = true;
|
|
397
|
+
return fCallback();
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
var tmpOp = pQuery.query.parameters.mongoOperation;
|
|
401
|
+
if (!tmpOp || tmpOp.operation === 'noop')
|
|
402
|
+
{
|
|
403
|
+
tmpResult.error = null;
|
|
404
|
+
tmpResult.value = 0;
|
|
405
|
+
tmpResult.executed = true;
|
|
406
|
+
return fCallback();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
var tmpCollection = tmpDB.collection(tmpOp.collection);
|
|
410
|
+
var tmpUpdate = replaceSentinels(JSON.parse(JSON.stringify(tmpOp.update)));
|
|
411
|
+
|
|
412
|
+
tmpCollection.updateMany(tmpOp.filter, tmpUpdate)
|
|
413
|
+
.then(function (pUpdateResult)
|
|
414
|
+
{
|
|
415
|
+
tmpResult.error = null;
|
|
416
|
+
tmpResult.value = pUpdateResult.modifiedCount;
|
|
417
|
+
tmpResult.executed = true;
|
|
418
|
+
return fCallback();
|
|
419
|
+
})
|
|
420
|
+
.catch(function (pError)
|
|
421
|
+
{
|
|
422
|
+
tmpResult.error = pError;
|
|
423
|
+
tmpResult.value = false;
|
|
424
|
+
tmpResult.executed = true;
|
|
425
|
+
return fCallback();
|
|
426
|
+
});
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
var Count = function (pQuery, fCallback)
|
|
430
|
+
{
|
|
431
|
+
var tmpResult = pQuery.parameters.result;
|
|
432
|
+
|
|
433
|
+
pQuery.setDialect('MongoDB').buildCountQuery();
|
|
434
|
+
|
|
435
|
+
if (pQuery.logLevel > 0 ||
|
|
436
|
+
_GlobalLogLevel > 0)
|
|
437
|
+
{
|
|
438
|
+
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
var tmpDB = getDB();
|
|
442
|
+
if (!tmpDB)
|
|
443
|
+
{
|
|
444
|
+
tmpResult.error = new Error('No MongoDB connection available.');
|
|
445
|
+
tmpResult.executed = true;
|
|
446
|
+
return fCallback();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
var tmpOp = pQuery.query.parameters.mongoOperation;
|
|
450
|
+
var tmpCollection = tmpDB.collection(tmpOp.collection);
|
|
451
|
+
|
|
452
|
+
if (tmpOp.distinct && tmpOp.distinctFields && tmpOp.distinctFields.length > 0)
|
|
453
|
+
{
|
|
454
|
+
// Use aggregation pipeline for distinct count
|
|
455
|
+
var tmpGroupId = {};
|
|
456
|
+
for (var i = 0; i < tmpOp.distinctFields.length; i++)
|
|
457
|
+
{
|
|
458
|
+
tmpGroupId[tmpOp.distinctFields[i]] = '$' + tmpOp.distinctFields[i];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
var tmpPipeline = [
|
|
462
|
+
{ $match: tmpOp.filter },
|
|
463
|
+
{ $group: { _id: tmpGroupId } },
|
|
464
|
+
{ $count: 'RowCount' }
|
|
465
|
+
];
|
|
466
|
+
|
|
467
|
+
tmpCollection.aggregate(tmpPipeline).toArray()
|
|
468
|
+
.then(function (pResults)
|
|
469
|
+
{
|
|
470
|
+
tmpResult.error = null;
|
|
471
|
+
tmpResult.value = (pResults.length > 0) ? pResults[0].RowCount : 0;
|
|
472
|
+
tmpResult.executed = true;
|
|
473
|
+
return fCallback();
|
|
474
|
+
})
|
|
475
|
+
.catch(function (pError)
|
|
476
|
+
{
|
|
477
|
+
tmpResult.error = pError;
|
|
478
|
+
tmpResult.value = false;
|
|
479
|
+
tmpResult.executed = true;
|
|
480
|
+
return fCallback();
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
else
|
|
484
|
+
{
|
|
485
|
+
tmpCollection.countDocuments(tmpOp.filter)
|
|
486
|
+
.then(function (pCount)
|
|
487
|
+
{
|
|
488
|
+
tmpResult.error = null;
|
|
489
|
+
tmpResult.value = pCount;
|
|
490
|
+
tmpResult.executed = true;
|
|
491
|
+
return fCallback();
|
|
492
|
+
})
|
|
493
|
+
.catch(function (pError)
|
|
494
|
+
{
|
|
495
|
+
tmpResult.error = pError;
|
|
496
|
+
tmpResult.value = false;
|
|
497
|
+
tmpResult.executed = true;
|
|
498
|
+
return fCallback();
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
var tmpNewProvider = (
|
|
504
|
+
{
|
|
505
|
+
marshalRecordFromSourceToObject: marshalRecordFromSourceToObject,
|
|
506
|
+
|
|
507
|
+
Create: Create,
|
|
508
|
+
Read: Read,
|
|
509
|
+
Update: Update,
|
|
510
|
+
Delete: Delete,
|
|
511
|
+
Undelete: Undelete,
|
|
512
|
+
Count: Count,
|
|
513
|
+
|
|
514
|
+
getProvider: getProvider,
|
|
515
|
+
providerCreatesSupported: true,
|
|
516
|
+
|
|
517
|
+
new: createNew
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
return tmpNewProvider;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return createNew();
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
module.exports = new MeadowProvider();
|