8
8
/*!
9
9
* Module dependencies
10
10
*/
11
- const bson = require ( 'bson' ) ;
12
11
const g = require ( 'strong-globalize' ) ( ) ;
13
12
const mongodb = require ( 'mongodb' ) ;
14
- const urlParser = require ( 'mongodb/lib/url_parser' ) ;
13
+ const urlParser = require ( 'mongodb/lib/connection_string' ) . parseOptions ;
15
14
const util = require ( 'util' ) ;
16
15
const async = require ( 'async' ) ;
17
16
const Connector = require ( 'loopback-connector' ) . Connector ;
@@ -29,7 +28,7 @@ exports.ObjectID = ObjectID;
29
28
* @returns {ObjectID }
30
29
*/
31
30
function ObjectID ( id ) {
32
- if ( id instanceof mongodb . ObjectID ) {
31
+ if ( id instanceof mongodb . ObjectId ) {
33
32
return id ;
34
33
}
35
34
if ( typeof id !== 'string' ) {
@@ -40,7 +39,7 @@ function ObjectID(id) {
40
39
// hex string. For LoopBack, we only allow 24-byte hex string, but 12-byte
41
40
// string such as 'line-by-line' should be kept as string
42
41
if ( ObjectIdValueRegex . test ( id ) ) {
43
- return new bson . ObjectID ( id ) ;
42
+ return new mongodb . ObjectId ( id ) ;
44
43
} else {
45
44
return id ;
46
45
}
@@ -113,10 +112,9 @@ exports.initialize = function initializeDataSource(dataSource, callback) {
113
112
fsync : s . fsync || null ,
114
113
} ;
115
114
s . url = s . url || generateMongoDBURL ( s ) ;
116
- s . useNewUrlParser = s . useNewUrlParser !== false ;
117
- s . useUnifiedTopology = s . useUnifiedTopology !== false ;
115
+ // useNewUrlParser and useUnifiedTopology are default now
118
116
dataSource . connector = new MongoDB ( s , dataSource ) ;
119
- dataSource . ObjectID = mongodb . ObjectID ;
117
+ dataSource . ObjectID = mongodb . ObjectId ;
120
118
121
119
if ( callback ) {
122
120
if ( s . lazyConnect ) {
@@ -285,8 +283,6 @@ MongoDB.prototype.connect = function(callback) {
285
283
'validateOptions' ,
286
284
'appname' ,
287
285
'auth' ,
288
- 'user' ,
289
- 'password' ,
290
286
'authMechanism' ,
291
287
'compression' ,
292
288
'readPreferenceTags' ,
@@ -354,17 +350,45 @@ MongoDB.prototype.connect = function(callback) {
354
350
}
355
351
self . client = client ;
356
352
// The database name might be in the url
357
- return urlParser ( self . settings . url , self . settings , function ( err , url ) {
358
- if ( err ) {
359
- onError ( err ) ;
360
- return ;
361
- }
353
+ try {
354
+ const url = urlParser ( self . settings . url , validOptions ) ; // only supports the validURL options now
355
+ // See https://github.com/mongodb/mongodb/blob/6.0.1/lib/mongodb.d.ts#L3854
356
+ const validDbOptionNames = [
357
+ 'authSource' ,
358
+ 'forceServerObjectId' ,
359
+ 'readPreference' ,
360
+ 'pkFactory' ,
361
+ 'readConcern' ,
362
+ 'retryWrites' ,
363
+ 'checkKeys' ,
364
+ 'serializeFunctions' ,
365
+ 'ignoreUndefined' ,
366
+ 'promoteLongs' ,
367
+ 'promoteBuffers' ,
368
+ 'promoteValues' ,
369
+ 'fieldsAsRaw' ,
370
+ 'bsonRegExp' ,
371
+ 'raw' ,
372
+ 'writeConcern' ,
373
+ 'logger' ,
374
+ 'loggerLevel' ,
375
+ ] ;
376
+ const dbOptions = url . db_options || self . settings ;
377
+ const dbOptionKeys = Object . keys ( dbOptions ) ;
378
+ const validDbOptions = { } ;
379
+ dbOptionKeys . forEach ( function ( option ) {
380
+ if ( validDbOptionNames . indexOf ( option ) > - 1 ) {
381
+ validDbOptions [ option ] = dbOptions [ option ] ;
382
+ }
383
+ } ) ;
362
384
self . db = client . db (
363
385
url . dbName || self . settings . database ,
364
- url . db_options || self . settings ,
386
+ validDbOptions ,
365
387
) ;
366
388
if ( callback ) callback ( err , self . db ) ;
367
- } ) ;
389
+ } catch ( e ) {
390
+ onError ( e ) ;
391
+ }
368
392
} ) ;
369
393
}
370
394
} ;
@@ -498,7 +522,13 @@ MongoDB.prototype.execute = function(modelName, command) {
498
522
499
523
// Topology is destroyed when the server is disconnected
500
524
// Execute if DB is connected and functional otherwise connect/reconnect first
501
- if ( self . db && self . db . topology && ! self . db . topology . isDestroyed ( ) ) {
525
+ if (
526
+ self . db && (
527
+ ! self . db . topology || ( self . db . topology && ! self . db . topology . isDestroyed ( ) )
528
+ )
529
+ ) {
530
+ doExecute ( ) ;
531
+ } else if ( self . db && ! self . db . topology ) {
502
532
doExecute ( ) ;
503
533
} else {
504
534
if ( self . db ) {
@@ -545,7 +575,7 @@ MongoDB.prototype.execute = function(modelName, command) {
545
575
'execute' ,
546
576
context ,
547
577
function ( context , done ) {
548
- args [ args . length - 1 ] = function ( err , result ) {
578
+ const observerCallback = function ( err , result ) {
549
579
if ( err ) {
550
580
debug ( 'Error: ' , err ) ;
551
581
} else {
@@ -554,8 +584,23 @@ MongoDB.prototype.execute = function(modelName, command) {
554
584
}
555
585
done ( err , result ) ;
556
586
} ;
557
- debug ( 'MongoDB: model=%s command=%s' , modelName , command , args ) ;
558
- return collection [ command ] . apply ( collection , args ) ;
587
+
588
+ // args had callback removed
589
+ if ( command === 'find' ) {
590
+ // find does not support callback, remove and use a toArray with this callback
591
+ args . pop ( ) ;
592
+ debug ( 'MongoDB: model=%s command=%s' , modelName , command , args ) ;
593
+ try {
594
+ const cursor = collection [ command ] . apply ( collection , args ) ;
595
+ return observerCallback ( null , cursor ) ;
596
+ } catch ( err ) {
597
+ return observerCallback ( err , null ) ;
598
+ }
599
+ } else {
600
+ args [ args . length - 1 ] = observerCallback ;
601
+ debug ( 'MongoDB: model=%s command=%s' , modelName , command , args ) ;
602
+ return collection [ command ] . apply ( collection , args ) ;
603
+ }
559
604
} ,
560
605
callback ,
561
606
) ;
@@ -620,7 +665,7 @@ MongoDB.prototype.create = function(modelName, data, options, callback) {
620
665
if ( err ) {
621
666
return callback ( err ) ;
622
667
}
623
- idValue = result . ops [ 0 ] . _id ;
668
+ idValue = result . insertedId ;
624
669
625
670
try {
626
671
idValue = self . coerceId ( modelName , idValue , options ) ;
@@ -674,18 +719,13 @@ MongoDB.prototype.save = function(modelName, data, options, callback) {
674
719
}
675
720
676
721
const info = { } ;
677
- if ( result && result . result ) {
678
- // create result formats:
679
- // { ok: 1, n: 1, upserted: [ [Object] ] }
680
- // { ok: 1, nModified: 0, n: 1, upserted: [ [Object] ] }
681
- //
682
- // update result formats:
683
- // { ok: 1, n: 1 }
684
- // { ok: 1, nModified: 1, n: 1 }
685
- if ( result . result . ok === 1 && result . result . n === 1 ) {
686
- info . isNewInstance = ! ! result . result . upserted ;
722
+ if ( result ) {
723
+ // new 4.0 result formats:
724
+ // { acknowledged: true, modifiedCount: 1, upsertedCount: 1, : modifiedCount: 1}
725
+ if ( result . acknowledged === true && ( result . matchedCount === 1 || result . upsertedCount === 1 ) ) {
726
+ info . isNewInstance = result . upsertedCount === 1 ;
687
727
} else {
688
- debug ( 'save result format not recognized: %j' , result . result ) ;
728
+ debug ( 'save result format not recognized: %j' , result ) ;
689
729
}
690
730
}
691
731
@@ -854,7 +894,8 @@ MongoDB.prototype.updateOrCreate = function updateOrCreate(
854
894
data ,
855
895
buildOptions ( {
856
896
upsert : true ,
857
- returnOriginal : false ,
897
+ returnNewDocument : true ,
898
+ returnDocument : 'after' , // ensures new document gets returned
858
899
sort : [ [ '_id' , 'asc' ] ] ,
859
900
} , options ) ,
860
901
function ( err , result ) {
@@ -922,9 +963,9 @@ MongoDB.prototype.destroy = function destroy(modelName, id, options, callback) {
922
963
if ( self . debug ) {
923
964
debug ( 'delete.callback' , modelName , id , err , result ) ;
924
965
}
925
- let res = result && result . result ;
966
+ let res = result ;
926
967
if ( res ) {
927
- res = { count : res . n } ;
968
+ res = { count : res . deletedCount } ;
928
969
}
929
970
if ( callback ) {
930
971
callback ( err , res ) ;
@@ -1523,7 +1564,7 @@ MongoDB.prototype.destroyAll = function destroyAll(
1523
1564
1524
1565
if ( self . debug ) debug ( 'destroyAll.callback' , modelName , where , err , info ) ;
1525
1566
1526
- const affectedCount = info . result ? info . result . n : undefined ;
1567
+ const affectedCount = info ? info . deletedCount : undefined ;
1527
1568
1528
1569
if ( callback ) {
1529
1570
callback ( err , { count : affectedCount } ) ;
@@ -1614,7 +1655,7 @@ MongoDB.prototype.replaceWithOptions = function(modelName, id, data, options, cb
1614
1655
if ( err ) return cb && cb ( err ) ;
1615
1656
let result ;
1616
1657
const cbInfo = { } ;
1617
- if ( info . result && info . result . n == 1 ) {
1658
+ if ( info && ( info . matchedCount === 1 || info . upsertedCount === 1 ) ) {
1618
1659
result = self . fromDatabase ( modelName , data ) ;
1619
1660
delete result . _id ;
1620
1661
result [ idName ] = id ;
@@ -1625,8 +1666,8 @@ MongoDB.prototype.replaceWithOptions = function(modelName, id, data, options, cb
1625
1666
// replace result formats:
1626
1667
// 2.4.x: { ok: 1, n: 1 }
1627
1668
// { ok: 1, nModified: 1, n: 1 }
1628
- if ( info . result . nModified !== undefined ) {
1629
- cbInfo . isNewInstance = info . result . nModified === 0 ;
1669
+ if ( info . modifiedCount !== undefined ) {
1670
+ cbInfo . isNewInstance = info . modifiedCount === 0 ;
1630
1671
}
1631
1672
} else {
1632
1673
result = undefined ;
@@ -1754,7 +1795,7 @@ MongoDB.prototype.update = MongoDB.prototype.updateAll = function updateAll(
1754
1795
if ( self . debug )
1755
1796
debug ( 'updateAll.callback' , modelName , where , updateData , err , info ) ;
1756
1797
1757
- const affectedCount = info . result ? info . result . n : undefined ;
1798
+ const affectedCount = info ? info . matchedCount : undefined ;
1758
1799
1759
1800
if ( cb ) {
1760
1801
cb ( err , { count : affectedCount } ) ;
@@ -1805,7 +1846,8 @@ MongoDB.prototype.upsertWithWhere = function upsertWithWhere(
1805
1846
updateData ,
1806
1847
buildOptions ( {
1807
1848
upsert : true ,
1808
- returnOriginal : false ,
1849
+ returnNewDocument : true ,
1850
+ returnDocument : 'after' , // ensures new documents get returned
1809
1851
sort : [ [ '_id' , 'asc' ] ] ,
1810
1852
} , options ) ,
1811
1853
function ( err , result ) {
@@ -2040,7 +2082,7 @@ MongoDB.prototype.automigrate = function(models, cb) {
2040
2082
) ;
2041
2083
if (
2042
2084
! (
2043
- err . name === 'MongoError ' &&
2085
+ err . name === 'MongoServerError ' &&
2044
2086
err . ok === 0 &&
2045
2087
err . errmsg === 'ns not found'
2046
2088
)
@@ -2188,7 +2230,7 @@ function isObjectIDProperty(modelCtor, propDef, value, options) {
2188
2230
( Array . isArray ( value ) && value . every ( ( v ) => typeof v === 'string' && v . match ( ObjectIdValueRegex ) ) ) ) {
2189
2231
if ( isStoredAsObjectID ( propDef ) ) return true ;
2190
2232
else return ! isStrictObjectIDCoercionEnabled ( modelCtor , options ) ;
2191
- } else if ( value instanceof mongodb . ObjectID ) {
2233
+ } else if ( value instanceof mongodb . ObjectId ) {
2192
2234
return true ;
2193
2235
} else {
2194
2236
return false ;
@@ -2285,7 +2327,7 @@ function optimizedFindOrCreate(modelName, filter, data, options, callback) {
2285
2327
let value = result . value ;
2286
2328
const created = ! ! result . lastErrorObject . upserted ;
2287
2329
2288
- if ( created && ( value == null || Object . keys ( value ) . length == 0 ) ) {
2330
+ if ( created && ( value == null || Object . keys ( value ) . length === 0 ) ) {
2289
2331
value = data ;
2290
2332
self . setIdValue ( modelName , value , result . lastErrorObject . upserted ) ;
2291
2333
} else {
@@ -2336,7 +2378,6 @@ function visitAllProperties(data, modelCtor, visitor) {
2336
2378
} else {
2337
2379
visitor ( modelCtor , value , def , ( newValue ) => { data [ p ] = newValue ; } ) ;
2338
2380
}
2339
- continue ;
2340
2381
}
2341
2382
}
2342
2383
0 commit comments