1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657 |
- 'use strict';
-
-
-
- const Aggregate = require('./aggregate');
- const ChangeStream = require('./cursor/ChangeStream');
- const Document = require('./document');
- const DocumentNotFoundError = require('./error').DocumentNotFoundError;
- const DivergentArrayError = require('./error').DivergentArrayError;
- const Error = require('./error');
- const EventEmitter = require('events').EventEmitter;
- const MongooseMap = require('./types/map');
- const OverwriteModelError = require('./error').OverwriteModelError;
- const PromiseProvider = require('./promise_provider');
- const Query = require('./query');
- const Schema = require('./schema');
- const VersionError = require('./error').VersionError;
- const ParallelSaveError = require('./error').ParallelSaveError;
- const applyQueryMiddleware = require('./helpers/query/applyQueryMiddleware');
- const applyHooks = require('./helpers/model/applyHooks');
- const applyMethods = require('./helpers/model/applyMethods');
- const applyStatics = require('./helpers/model/applyStatics');
- const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
- const assignRawDocsToIdStructure = require('./helpers/populate/assignRawDocsToIdStructure');
- const castBulkWrite = require('./helpers/model/castBulkWrite');
- const discriminator = require('./helpers/model/discriminator');
- const getDiscriminatorByValue = require('./queryhelpers').getDiscriminatorByValue;
- const immediate = require('./helpers/immediate');
- const internalToObjectOptions = require('./options').internalToObjectOptions;
- const isPathExcluded = require('./helpers/projection/isPathExcluded');
- const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
- const get = require('./helpers/get');
- const getSchemaTypes = require('./helpers/populate/getSchemaTypes');
- const getVirtual = require('./helpers/populate/getVirtual');
- const leanPopulateMap = require('./helpers/populate/leanPopulateMap');
- const modifiedPaths = require('./helpers/update/modifiedPaths');
- const mpath = require('mpath');
- const normalizeRefPath = require('./helpers/populate/normalizeRefPath');
- const parallel = require('async/parallel');
- const parallelLimit = require('async/parallelLimit');
- const setParentPointers = require('./helpers/schema/setParentPointers');
- const util = require('util');
- const utils = require('./utils');
-
- const VERSION_WHERE = 1;
- const VERSION_INC = 2;
- const VERSION_ALL = VERSION_WHERE | VERSION_INC;
-
- const modelCollectionSymbol = Symbol.for('mongoose#Model#collection');
- const modelSymbol = require('./helpers/symbols').modelSymbol;
- const schemaMixedSymbol = require('./schema/symbols').schemaMixedSymbol;
-
- /**
- * A Model is a class that's your primary tool for interacting with MongoDB.
- * An instance of a Model is called a [Document](./api.html#Document).
- *
- * In Mongoose, the term "Model" refers to subclasses of the `mongoose.Model`
- * class. You should not use the `mongoose.Model` class directly. The
- * [`mongoose.model()`](./api.html#mongoose_Mongoose-model) and
- * [`connection.model()`](./api.html#connection_Connection-model) functions
- * create subclasses of `mongoose.Model` as shown below.
- *
- * ####Example:
- *
- * // `UserModel` is a "Model", a subclass of `mongoose.Model`.
- * const UserModel = mongoose.model('User', new Schema({ name: String }));
- *
- *
- * const userDoc = new UserModel({ name: 'Foo' });
- * await userDoc.save();
- *
- *
- * const userFromDb = await UserModel.findOne({ name: 'Foo' });
- *
- * @param {Object} doc values for initial set
- * @param [fields] optional object containing the fields that were selected in the query which returned this document. You do **not** need to set this parameter to ensure Mongoose handles your [query projetion](./api.html#query_Query-select).
- * @inherits Document http://mongoosejs.com/docs/api.html#document-js
- * @event `error`: If listening to this event, 'error' is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
- * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
- * @event `index-single-start`: Emitted when an individual index starts within `Model#ensureIndexes`. The fields and options being used to build the index are also passed with the event.
- * @event `index-single-done`: Emitted when an individual index finishes within `Model#ensureIndexes`. If an error occurred it is passed with the event. The fields, options, and index name are also passed.
- * @api public
- */
-
- function Model(doc, fields, skipId) {
- if (fields instanceof Schema) {
- throw new TypeError('2nd argument to `Model` must be a POJO or string, ' +
- '**not** a schema. Make sure you\'re calling `mongoose.model()`, not ' +
- '`mongoose.Model()`.');
- }
- Document.call(this, doc, fields, skipId);
- }
-
-
-
- Model.prototype.__proto__ = Document.prototype;
- Model.prototype.$isMongooseModelPrototype = true;
-
-
-
- Model.prototype.db;
-
-
-
- Model.prototype.collection;
-
-
-
- Model.prototype.modelName;
-
-
-
- Model.prototype.$where;
-
-
-
- Model.prototype.baseModelName;
-
-
-
- Model.events;
-
-
-
- Model._middleware;
-
-
-
- Model.prototype.$__handleSave = function(options, callback) {
- const _this = this;
- let i;
- let keys;
- let len;
- let saveOptions = {};
-
- if ('safe' in options) {
- _handleSafe(options);
- }
- applyWriteConcern(this.schema, options);
- if ('w' in options) {
- saveOptions.w = options.w;
- }
- if ('j' in options) {
- saveOptions.j = options.j;
- }
- if ('wtimeout' in options) {
- saveOptions.wtimeout = options.wtimeout;
- }
- if ('checkKeys' in options) {
- saveOptions.checkKeys = options.checkKeys;
- }
-
- const session = 'session' in options ? options.session : this.$session();
- if (session != null) {
- saveOptions.session = session;
- this.$session(session);
- }
-
- if (Object.keys(saveOptions).length === 0) {
- saveOptions = null;
- }
-
- if (this.isNew) {
-
- const obj = this.toObject(internalToObjectOptions);
-
- if ((obj || {})._id === void 0) {
-
-
-
-
-
- setTimeout(function() {
- callback(new Error('document must have an _id before saving'));
- }, 0);
- return;
- }
-
- this.$__version(true, obj);
- this[modelCollectionSymbol].insertOne(obj, saveOptions, function(err, ret) {
- if (err) {
- _this.isNew = true;
- _this.emit('isNew', true);
- _this.constructor.emit('isNew', true);
-
- callback(err, null);
- return;
- }
-
- callback(null, ret);
- });
- this.$__reset();
- this.isNew = false;
- this.emit('isNew', false);
- this.constructor.emit('isNew', false);
-
- this.$__.inserting = true;
- } else {
-
-
- this.$__.inserting = false;
-
- const delta = this.$__delta();
-
- if (delta) {
- if (delta instanceof Error) {
- callback(delta);
- return;
- }
-
- const where = this.$__where(delta[0]);
- if (where instanceof Error) {
- callback(where);
- return;
- }
-
- if (this.$where) {
- keys = Object.keys(this.$where);
- len = keys.length;
- for (i = 0; i < len; ++i) {
- where[keys[i]] = this.$where[keys[i]];
- }
- }
-
- this[modelCollectionSymbol].updateOne(where, delta[1], saveOptions, function(err, ret) {
- if (err) {
- callback(err);
- return;
- }
- ret.$where = where;
- callback(null, ret);
- });
- } else {
- this.$__reset();
- callback();
- return;
- }
-
- this.emit('isNew', false);
- this.constructor.emit('isNew', false);
- }
- };
-
-
-
- Model.prototype.$__save = function(options, callback) {
- this.$__handleSave(options, (error, result) => {
- if (error) {
- return this.schema.s.hooks.execPost('save:error', this, [this], { error: error }, function(error) {
- callback(error);
- });
- }
-
-
- const modifiedPaths = this.modifiedPaths();
-
- this.$__reset();
-
- let numAffected = 0;
- if (get(options, 'safe.w') !== 0 && get(options, 'w') !== 0) {
-
-
- if (result) {
- if (Array.isArray(result)) {
- numAffected = result.length;
- } else if (result.result && result.result.n !== undefined) {
- numAffected = result.result.n;
- } else if (result.result && result.result.nModified !== undefined) {
- numAffected = result.result.nModified;
- } else {
- numAffected = result;
- }
- }
-
-
- if (this.$__.version && !this.$__.inserting) {
- const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
- this.$__.version = undefined;
-
- const key = this.schema.options.versionKey;
- const version = this.getValue(key) || 0;
-
- if (numAffected <= 0) {
-
- const err = options.$versionError || new VersionError(this, version, modifiedPaths);
- return callback(err);
- }
-
-
- if (doIncrement) {
- this.setValue(key, version + 1);
- }
- }
-
- if (result != null && numAffected <= 0) {
- error = new DocumentNotFoundError(result.$where);
- return this.schema.s.hooks.execPost('save:error', this, [this], { error: error }, function(error) {
- callback(error);
- });
- }
- }
- this.$__.saving = undefined;
- this.emit('save', this, numAffected);
- this.constructor.emit('save', this, numAffected);
- callback(null, this);
- });
- };
-
-
-
- function generateVersionError(doc, modifiedPaths) {
- const key = doc.schema.options.versionKey;
- if (!key) {
- return null;
- }
- const version = doc.getValue(key) || 0;
- return new VersionError(doc, version, modifiedPaths);
- }
-
-
-
- Model.prototype.save = function(options, fn) {
- let parallelSave;
-
- if (this.$__.saving) {
- parallelSave = new ParallelSaveError(this);
- } else {
- this.$__.saving = new ParallelSaveError(this);
- }
-
- if (typeof options === 'function') {
- fn = options;
- options = undefined;
- }
-
- if (options != null) {
- options = utils.clone(options);
- } else {
- options = {};
- }
-
- if (fn) {
- fn = this.constructor.$wrapCallback(fn);
- }
-
- options.$versionError = generateVersionError(this, this.modifiedPaths());
-
- return utils.promiseOrCallback(fn, cb => {
- if (parallelSave) {
- this.$__handleReject(parallelSave);
- return cb(parallelSave);
- }
-
- this.$__save(options, error => {
- this.$__.saving = undefined;
-
- if (error) {
- this.$__handleReject(error);
- return cb(error);
- }
- cb(null, this);
- });
- }, this.constructor.events);
- };
-
-
- function shouldSkipVersioning(self, path) {
- const skipVersioning = self.schema.options.skipVersioning;
- if (!skipVersioning) return false;
-
-
- path = path.replace(/\.\d+\./, '.');
-
- return skipVersioning[path];
- }
-
-
-
- function operand(self, where, delta, data, val, op) {
-
- op || (op = '$set');
- if (!delta[op]) delta[op] = {};
- delta[op][data.path] = val;
-
-
- if (self.schema.options.versionKey === false) return;
-
-
- if (shouldSkipVersioning(self, data.path)) return;
-
-
- if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;
-
- switch (op) {
- case '$set':
- case '$unset':
- case '$pop':
- case '$pull':
- case '$pullAll':
- case '$push':
- case '$addToSet':
- break;
- default:
-
- return;
- }
-
-
-
-
-
- if (op === '$push' || op === '$addToSet' || op === '$pullAll' || op === '$pull') {
- self.$__.version = VERSION_INC;
- } else if (/^\$p/.test(op)) {
-
- self.increment();
- } else if (Array.isArray(val)) {
-
- self.increment();
- } else if (/\.\d+\.|\.\d+$/.test(data.path)) {
-
-
- self.$__.version = VERSION_WHERE;
- }
- }
-
-
-
- function handleAtomics(self, where, delta, data, value) {
- if (delta.$set && delta.$set[data.path]) {
-
- return;
- }
-
- if (typeof value.$__getAtomics === 'function') {
- value.$__getAtomics().forEach(function(atomic) {
- const op = atomic[0];
- const val = atomic[1];
- operand(self, where, delta, data, val, op);
- });
- return;
- }
-
-
-
- const atomics = value._atomics;
- const ops = Object.keys(atomics);
- let i = ops.length;
- let val;
- let op;
-
- if (i === 0) {
-
-
- if (utils.isMongooseObject(value)) {
- value = value.toObject({depopulate: 1, _isNested: true});
- } else if (value.valueOf) {
- value = value.valueOf();
- }
-
- return operand(self, where, delta, data, value);
- }
-
- function iter(mem) {
- return utils.isMongooseObject(mem)
- ? mem.toObject({depopulate: 1, _isNested: true})
- : mem;
- }
-
- while (i--) {
- op = ops[i];
- val = atomics[op];
-
- if (utils.isMongooseObject(val)) {
- val = val.toObject({depopulate: true, transform: false, _isNested: true});
- } else if (Array.isArray(val)) {
- val = val.map(iter);
- } else if (val.valueOf) {
- val = val.valueOf();
- }
-
- if (op === '$addToSet') {
- val = {$each: val};
- }
-
- operand(self, where, delta, data, val, op);
- }
- }
-
-
-
- Model.prototype.$__delta = function() {
- const dirty = this.$__dirty();
- if (!dirty.length && VERSION_ALL !== this.$__.version) {
- return;
- }
-
- const where = {};
- const delta = {};
- const len = dirty.length;
- const divergent = [];
- let d = 0;
-
- where._id = this._doc._id;
-
-
- if (get(where, '_id.$__', null) != null) {
- where._id = where._id.toObject({ transform: false, depopulate: true });
- }
-
- for (; d < len; ++d) {
- const data = dirty[d];
- let value = data.value;
-
- const match = checkDivergentArray(this, data.path, value);
- if (match) {
- divergent.push(match);
- continue;
- }
-
- const pop = this.populated(data.path, true);
- if (!pop && this.$__.selected) {
-
-
- const pathSplit = data.path.split('.');
- const top = pathSplit[0];
- if (this.$__.selected[top] && this.$__.selected[top].$elemMatch) {
-
- if (pathSplit.length > 1 && pathSplit[1] == 0 && typeof where[top] === 'undefined') {
- where[top] = this.$__.selected[top];
- pathSplit[1] = '$';
- data.path = pathSplit.join('.');
- }
-
- else {
- divergent.push(data.path);
- continue;
- }
- }
- }
-
- if (divergent.length) continue;
-
- if (value === undefined) {
- operand(this, where, delta, data, 1, '$unset');
- } else if (value === null) {
- operand(this, where, delta, data, null);
- } else if (value._path && value._atomics) {
-
- handleAtomics(this, where, delta, data, value);
- } else if (value._path && Buffer.isBuffer(value)) {
-
- value = value.toObject();
- operand(this, where, delta, data, value);
- } else {
- value = utils.clone(value, {
- depopulate: true,
- transform: false,
- virtuals: false,
- _isNested: true
- });
- operand(this, where, delta, data, value);
- }
- }
-
- if (divergent.length) {
- return new DivergentArrayError(divergent);
- }
-
- if (this.$__.version) {
- this.$__version(where, delta);
- }
-
- return [where, delta];
- };
-
-
-
- function checkDivergentArray(doc, path, array) {
-
- const pop = doc.populated(path, true);
-
- if (!pop && doc.$__.selected) {
-
-
- const top = path.split('.')[0];
- if (doc.$__.selected[top + '.$']) {
- return top;
- }
- }
-
- if (!(pop && array && array.isMongooseArray)) return;
-
-
-
-
-
-
-
-
-
-
- const check = pop.options.match ||
- pop.options.options && utils.object.hasOwnProperty(pop.options.options, 'limit') ||
- pop.options.options && pop.options.options.skip ||
- pop.options.select &&
- (pop.options.select._id === 0 ||
- /\s?-_id\s?/.test(pop.options.select));
-
- if (check) {
- const atomics = array._atomics;
- if (Object.keys(atomics).length === 0 || atomics.$set || atomics.$pop) {
- return path;
- }
- }
- }
-
-
-
- Model.prototype.$__version = function(where, delta) {
- const key = this.schema.options.versionKey;
-
- if (where === true) {
-
- if (key) this.setValue(key, delta[key] = 0);
- return;
- }
-
-
-
-
-
-
-
- if (!this.isSelected(key)) {
- return;
- }
-
-
- if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) {
- const value = this.getValue(key);
- if (value != null) where[key] = value;
- }
-
- if (VERSION_INC === (VERSION_INC & this.$__.version)) {
- if (get(delta.$set, key, null) != null) {
-
-
-
- ++delta.$set[key];
- } else {
- delta.$inc = delta.$inc || {};
- delta.$inc[key] = 1;
- }
- }
- };
-
-
-
- Model.prototype.increment = function increment() {
- this.$__.version = VERSION_ALL;
- return this;
- };
-
-
-
- Model.prototype.$__where = function _where(where) {
- where || (where = {});
-
- if (!where._id) {
- where._id = this._doc._id;
- }
-
- if (this._doc._id === void 0) {
- return new Error('No _id found on document!');
- }
-
- return where;
- };
-
-
-
- Model.prototype.remove = function remove(options, fn) {
- if (typeof options === 'function') {
- fn = options;
- options = undefined;
- }
-
- if (!options) {
- options = {};
- }
-
- if (fn) {
- fn = this.constructor.$wrapCallback(fn);
- }
-
- return utils.promiseOrCallback(fn, cb => {
- this.$__remove(options, cb);
- }, this.constructor.events);
- };
-
-
-
- Model.prototype.delete = Model.prototype.remove;
-
-
-
- Model.prototype.$__remove = function $__remove(options, cb) {
- if (this.$__.isDeleted) {
- return immediate(() => cb(null, this));
- }
-
- const where = this.$__where();
- if (where instanceof Error) {
- return cb(where);
- }
-
- this[modelCollectionSymbol].deleteOne(where, options, err => {
- if (!err) {
- this.$__.isDeleted = true;
- this.emit('remove', this);
- this.constructor.emit('remove', this);
- return cb(null, this);
- }
- this.$__.isDeleted = false;
- cb(err);
- });
- };
-
-
-
- Model.prototype.model = function model(name) {
- return this.db.model(name);
- };
-
-
-
- Model.discriminator = function(name, schema, value) {
- let model;
- if (typeof name === 'function') {
- model = name;
- name = utils.getFunctionName(model);
- if (!(model.prototype instanceof Model)) {
- throw new Error('The provided class ' + name + ' must extend Model');
- }
- }
-
- schema = discriminator(this, name, schema, value);
- if (this.db.models[name]) {
- throw new OverwriteModelError(name);
- }
-
- schema.$isRootDiscriminator = true;
-
- model = this.db.model(model || name, schema, this.collection.name);
- this.discriminators[name] = model;
- const d = this.discriminators[name];
- d.prototype.__proto__ = this.prototype;
- Object.defineProperty(d, 'baseModelName', {
- value: this.modelName,
- configurable: true,
- writable: false
- });
-
-
- applyMethods(d, schema);
- applyStatics(d, schema);
-
- return d;
- };
-
-
-
-
-
- for (const i in EventEmitter.prototype) {
- Model[i] = EventEmitter.prototype[i];
- }
-
-
-
- Model.init = function init(callback) {
- this.schema.emit('init', this);
-
- if (this.$init != null) {
- if (callback) {
- this.$init.then(() => callback(), err => callback(err));
- return null;
- }
- return this.$init;
- }
-
-
-
-
-
- this.db.$internalEmitter.once('dropDatabase', () => {
- delete this.$init;
- });
-
- const Promise = PromiseProvider.get();
- const autoIndex = this.schema.options.autoIndex == null ?
- this.db.config.autoIndex :
- this.schema.options.autoIndex;
- const autoCreate = this.schema.options.autoCreate == null ?
- this.db.config.autoCreate :
- this.schema.options.autoCreate;
-
- const _ensureIndexes = autoIndex ?
- cb => this.ensureIndexes({ _automatic: true }, cb) :
- cb => cb();
- const _createCollection = autoCreate ?
- cb => this.createCollection({}, cb) :
- cb => cb();
-
- this.$init = new Promise((resolve, reject) => {
- _createCollection(error => {
- if (error) {
- return reject(error);
- }
- _ensureIndexes(error => {
- if (error) {
- return reject(error);
- }
- resolve(this);
- });
- });
- });
-
- if (callback) {
- this.$init.then(() => callback(), err => callback(err));
- this.$caught = true;
- return null;
- } else {
- const _catch = this.$init.catch;
- const _this = this;
- this.$init.catch = function() {
- this.$caught = true;
- return _catch.apply(_this.$init, arguments);
- };
- }
-
- return this.$init;
- };
-
-
-
-
- Model.createCollection = function createCollection(options, callback) {
- if (typeof options === 'string') {
- throw new Error('You can\'t specify a new collection name in Model.createCollection.' +
- 'This is not like Connection.createCollection. Only options are accepted here.');
- } else if (typeof options === 'function') {
- callback = options;
- options = null;
- }
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- const schemaCollation = get(this, 'schema.options.collation', null);
- if (schemaCollation != null) {
- options = Object.assign({ collation: schemaCollation }, options);
- }
-
- return utils.promiseOrCallback(callback, cb => {
- this.db.createCollection(this.collection.collectionName, options, utils.tick((error) => {
- if (error) {
- return cb(error);
- }
- this.collection = this.db.collection(this.collection.collectionName, options);
- cb(null, this.collection);
- }));
- }, this.events);
- };
-
-
-
- Model.syncIndexes = function syncIndexes(options, callback) {
- callback = this.$wrapCallback(callback);
-
- const dropNonSchemaIndexes = (cb) => {
- this.listIndexes((err, indexes) => {
- if (err != null) {
- return cb(err);
- }
-
- const schemaIndexes = this.schema.indexes();
- const toDrop = [];
-
- for (const index of indexes) {
- let found = false;
-
- if (index.key._id) {
- continue;
- }
-
- for (const schemaIndex of schemaIndexes) {
- const key = schemaIndex[0];
- const options = _decorateDiscriminatorIndexOptions(this,
- utils.clone(schemaIndex[1]));
-
-
- const optionKeys = ['unique', 'partialFilterExpression', 'sparse', 'expireAfterSeconds'];
- const indexCopy = Object.assign({}, index);
- for (const key of optionKeys) {
- if (!(key in options) && !(key in indexCopy)) {
- continue;
- }
- indexCopy[key] = options[key];
- }
- if (utils.deepEqual(key, index.key) &&
- utils.deepEqual(index, indexCopy)) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- toDrop.push(index.name);
- }
- }
-
- if (toDrop.length === 0) {
- return cb(null, []);
- }
-
- dropIndexes(toDrop, cb);
- });
- };
-
- const dropIndexes = (toDrop, cb) => {
- let remaining = toDrop.length;
- let error = false;
- toDrop.forEach(indexName => {
- this.collection.dropIndex(indexName, err => {
- if (err != null) {
- error = true;
- return cb(err);
- }
- if (!error) {
- --remaining || cb(null, toDrop);
- }
- });
- });
- };
-
- return utils.promiseOrCallback(callback, cb => {
- dropNonSchemaIndexes((err, dropped) => {
- if (err != null) {
- return cb(err);
- }
- this.createIndexes(options, err => {
- if (err != null) {
- return cb(err);
- }
- cb(null, dropped);
- });
- });
- }, this.events);
- };
-
-
-
- Model.listIndexes = function init(callback) {
- callback = this.$wrapCallback(callback);
-
- const _listIndexes = cb => {
- this.collection.listIndexes().toArray(cb);
- };
-
- return utils.promiseOrCallback(callback, cb => {
-
- if (this.collection.buffer) {
- this.collection.addQueue(_listIndexes, [cb]);
- } else {
- _listIndexes(cb);
- }
- }, this.events);
- };
-
-
-
- Model.ensureIndexes = function ensureIndexes(options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = null;
- }
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return utils.promiseOrCallback(callback, cb => {
- _ensureIndexes(this, options || {}, error => {
- if (error) {
- return cb(error);
- }
- cb(null);
- });
- }, this.events);
- };
-
-
-
- Model.createIndexes = function createIndexes(options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = {};
- }
- options = options || {};
- options.createIndex = true;
- return this.ensureIndexes(options, callback);
- };
-
-
-
- function _ensureIndexes(model, options, callback) {
- const indexes = model.schema.indexes();
-
- options = options || {};
-
- const done = function(err) {
- if (err && !model.$caught) {
- model.emit('error', err);
- }
- model.emit('index', err);
- callback && callback(err);
- };
-
- for (const index of indexes) {
- const keys = Object.keys(index[0]);
- if (keys.length === 1 && keys[0] === '_id' && index[0]._id !== 'hashed') {
- console.warn('mongoose: Cannot specify a custom index on `_id` for ' +
- 'model name "' + model.modelName + '", ' +
- 'MongoDB does not allow overwriting the default `_id` index. See ' +
- 'http://bit.ly/mongodb-id-index');
- }
- }
-
- if (!indexes.length) {
- immediate(function() {
- done();
- });
- return;
- }
-
-
-
- const indexSingleDone = function(err, fields, options, name) {
- model.emit('index-single-done', err, fields, options, name);
- };
- const indexSingleStart = function(fields, options) {
- model.emit('index-single-start', fields, options);
- };
-
- const create = function() {
- if (options._automatic) {
- if (model.schema.options.autoIndex === false ||
- (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) {
- return done();
- }
- }
-
- const index = indexes.shift();
- if (!index) {
- return done();
- }
-
- const indexFields = utils.clone(index[0]);
- const indexOptions = utils.clone(index[1]);
-
- _decorateDiscriminatorIndexOptions(model, indexOptions);
- if ('safe' in options) {
- _handleSafe(options);
- }
- applyWriteConcern(model.schema, indexOptions);
-
- indexSingleStart(indexFields, options);
- let useCreateIndex = !!model.base.options.useCreateIndex;
- if ('useCreateIndex' in model.db.config) {
- useCreateIndex = !!model.db.config.useCreateIndex;
- }
- if ('createIndex' in options) {
- useCreateIndex = !!options.createIndex;
- }
-
- const methodName = useCreateIndex ? 'createIndex' : 'ensureIndex';
- model.collection[methodName](indexFields, indexOptions, utils.tick(function(err, name) {
- indexSingleDone(err, indexFields, indexOptions, name);
- if (err) {
- return done(err);
- }
- create();
- }));
- };
-
- immediate(function() {
-
- if (options._automatic && !model.collection.collection) {
- model.collection.addQueue(create, []);
- } else {
- create();
- }
- });
- }
-
- function _decorateDiscriminatorIndexOptions(model, indexOptions) {
-
-
-
- if (model.baseModelName != null && indexOptions.unique &&
- !('partialFilterExpression' in indexOptions) &&
- !('sparse' in indexOptions)) {
- indexOptions.partialFilterExpression = {
- [model.schema.options.discriminatorKey]: model.modelName
- };
- }
- return indexOptions;
- }
-
- const safeDeprecationWarning = 'Mongoose: the `safe` option for `save()` is ' +
- 'deprecated. Use the `w` option instead: http://bit.ly/mongoose-save';
-
- const _handleSafe = util.deprecate(function _handleSafe(options) {
- if (options.safe) {
- if (typeof options.safe === 'boolean') {
- options.w = options.safe;
- delete options.safe;
- }
- if (typeof options.safe === 'object') {
- options.w = options.safe.w;
- options.j = options.safe.j;
- options.wtimeout = options.safe.wtimeout;
- delete options.safe;
- }
- }
- }, safeDeprecationWarning);
-
-
-
- Model.schema;
-
-
-
- Model.db;
-
-
-
- Model.collection;
-
-
-
- Model.base;
-
-
-
- Model.discriminators;
-
-
- Model.translateAliases = function translateAliases(fields) {
- const aliases = this.schema.aliases;
-
- if (typeof fields === 'object') {
-
- for (const key in fields) {
- if (aliases[key]) {
- fields[aliases[key]] = fields[key];
- delete fields[key];
- }
- }
-
- return fields;
- } else {
-
- return fields;
- }
- };
-
-
-
- Model.remove = function remove(conditions, callback) {
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- }
-
-
- const mq = new this.Query({}, {}, this, this.collection);
-
- callback = this.$wrapCallback(callback);
-
- return mq.remove(conditions, callback);
- };
-
-
-
- Model.deleteOne = function deleteOne(conditions, callback) {
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- }
-
-
- const mq = new this.Query(conditions, {}, this, this.collection);
-
- callback = this.$wrapCallback(callback);
-
- return mq.deleteOne(callback);
- };
-
-
-
- Model.deleteMany = function deleteMany(conditions, options, callback) {
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- options = null;
- }
- else if (typeof options === 'function') {
- callback = options;
- options = null;
- }
-
-
- const mq = new this.Query(conditions, {}, this, this.collection);
- mq.setOptions(options);
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return mq.deleteMany(callback);
- };
-
-
-
- Model.find = function find(conditions, projection, options, callback) {
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- projection = null;
- options = null;
- } else if (typeof projection === 'function') {
- callback = projection;
- projection = null;
- options = null;
- } else if (typeof options === 'function') {
- callback = options;
- options = null;
- }
-
- const mq = new this.Query({}, {}, this, this.collection);
- mq.select(projection);
-
- mq.setOptions(options);
- if (this.schema.discriminatorMapping &&
- this.schema.discriminatorMapping.isRoot &&
- mq.selectedInclusively()) {
-
- mq.select(this.schema.options.discriminatorKey);
- }
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return mq.find(conditions, callback);
- };
-
-
-
- Model.findById = function findById(id, projection, options, callback) {
- if (typeof id === 'undefined') {
- id = null;
- }
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return this.findOne({_id: id}, projection, options, callback);
- };
-
-
-
- Model.findOne = function findOne(conditions, projection, options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = null;
- } else if (typeof projection === 'function') {
- callback = projection;
- projection = null;
- options = null;
- } else if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- projection = null;
- options = null;
- }
-
-
- const mq = new this.Query({}, {}, this, this.collection);
- mq.select(projection);
-
- mq.setOptions(options);
- if (this.schema.discriminatorMapping &&
- this.schema.discriminatorMapping.isRoot &&
- mq.selectedInclusively()) {
- mq.select(this.schema.options.discriminatorKey);
- }
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return mq.findOne(conditions, callback);
- };
-
-
-
- Model.estimatedDocumentCount = function estimatedDocumentCount(options, callback) {
-
- const mq = new this.Query({}, {}, this, this.collection);
-
- callback = this.$wrapCallback(callback);
-
- return mq.estimatedDocumentCount(options, callback);
- };
-
-
-
- Model.countDocuments = function countDocuments(conditions, callback) {
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- }
-
-
- const mq = new this.Query({}, {}, this, this.collection);
-
- callback = this.$wrapCallback(callback);
-
- return mq.countDocuments(conditions, callback);
- };
-
-
-
- Model.count = function count(conditions, callback) {
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- }
-
-
- const mq = new this.Query({}, {}, this, this.collection);
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return mq.count(conditions, callback);
- };
-
-
-
- Model.distinct = function distinct(field, conditions, callback) {
-
- const mq = new this.Query({}, {}, this, this.collection);
-
- if (typeof conditions === 'function') {
- callback = conditions;
- conditions = {};
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return mq.distinct(field, conditions, callback);
- };
-
-
-
- Model.where = function where(path, val) {
- void val;
-
- const mq = new this.Query({}, {}, this, this.collection).find({});
- return mq.where.apply(mq, arguments);
- };
-
-
-
- Model.$where = function $where() {
- const mq = new this.Query({}, {}, this, this.collection).find({});
- return mq.$where.apply(mq, arguments);
- };
-
-
-
- Model.findOneAndUpdate = function(conditions, update, options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = null;
- } else if (arguments.length === 1) {
- if (typeof conditions === 'function') {
- const msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
- + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
- + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\n'
- + ' ' + this.modelName + '.findOneAndUpdate(update)\n'
- + ' ' + this.modelName + '.findOneAndUpdate()\n';
- throw new TypeError(msg);
- }
- update = conditions;
- conditions = undefined;
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- let fields;
- if (options) {
- fields = options.fields || options.projection;
- }
-
- update = utils.clone(update, {
- depopulate: true,
- _isNested: true
- });
-
- _decorateUpdateWithVersionKey(update, options, this.schema.options.versionKey);
-
- const mq = new this.Query({}, {}, this, this.collection);
- mq.select(fields);
-
- return mq.findOneAndUpdate(conditions, update, options, callback);
- };
-
-
-
- function _decorateUpdateWithVersionKey(update, options, versionKey) {
- if (!versionKey || !get(options, 'upsert', false)) {
- return;
- }
-
- const updatedPaths = modifiedPaths(update);
- if (!updatedPaths[versionKey]) {
- if (options.overwrite) {
- update[versionKey] = 0;
- } else {
- if (!update.$setOnInsert) {
- update.$setOnInsert = {};
- }
- update.$setOnInsert[versionKey] = 0;
- }
- }
- }
-
-
-
- Model.findByIdAndUpdate = function(id, update, options, callback) {
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
- if (arguments.length === 1) {
- if (typeof id === 'function') {
- const msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
- + ' ' + this.modelName + '.findByIdAndUpdate(id)\n'
- + ' ' + this.modelName + '.findByIdAndUpdate()\n';
- throw new TypeError(msg);
- }
- return this.findOneAndUpdate({_id: id}, undefined);
- }
-
-
- if (id instanceof Document) {
- id = id._id;
- }
-
- return this.findOneAndUpdate.call(this, {_id: id}, update, options, callback);
- };
-
-
-
- Model.findOneAndDelete = function(conditions, options, callback) {
- if (arguments.length === 1 && typeof conditions === 'function') {
- const msg = 'Model.findOneAndDelete(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findOneAndDelete(conditions, callback)\n'
- + ' ' + this.modelName + '.findOneAndDelete(conditions)\n'
- + ' ' + this.modelName + '.findOneAndDelete()\n';
- throw new TypeError(msg);
- }
-
- if (typeof options === 'function') {
- callback = options;
- options = undefined;
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- let fields;
- if (options) {
- fields = options.select;
- options.select = undefined;
- }
-
- const mq = new this.Query({}, {}, this, this.collection);
- mq.select(fields);
-
- return mq.findOneAndDelete(conditions, options, callback);
- };
-
-
-
- Model.findByIdAndDelete = function(id, options, callback) {
- if (arguments.length === 1 && typeof id === 'function') {
- const msg = 'Model.findByIdAndDelete(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findByIdAndDelete(id, callback)\n'
- + ' ' + this.modelName + '.findByIdAndDelete(id)\n'
- + ' ' + this.modelName + '.findByIdAndDelete()\n';
- throw new TypeError(msg);
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return this.findOneAndDelete({_id: id}, options, callback);
- };
-
-
-
- Model.findOneAndReplace = function(conditions, options, callback) {
- if (arguments.length === 1 && typeof conditions === 'function') {
- const msg = 'Model.findOneAndDelete(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findOneAndDelete(conditions, callback)\n'
- + ' ' + this.modelName + '.findOneAndDelete(conditions)\n'
- + ' ' + this.modelName + '.findOneAndDelete()\n';
- throw new TypeError(msg);
- }
-
- if (typeof options === 'function') {
- callback = options;
- options = undefined;
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- let fields;
- if (options) {
- fields = options.select;
- options.select = undefined;
- }
-
- const mq = new this.Query({}, {}, this, this.collection);
- mq.select(fields);
-
- return mq.findOneAndReplace(conditions, options, callback);
- };
-
-
-
- Model.findOneAndRemove = function(conditions, options, callback) {
- if (arguments.length === 1 && typeof conditions === 'function') {
- const msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
- + ' ' + this.modelName + '.findOneAndRemove(conditions)\n'
- + ' ' + this.modelName + '.findOneAndRemove()\n';
- throw new TypeError(msg);
- }
-
- if (typeof options === 'function') {
- callback = options;
- options = undefined;
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- let fields;
- if (options) {
- fields = options.select;
- options.select = undefined;
- }
-
- const mq = new this.Query({}, {}, this, this.collection);
- mq.select(fields);
-
- return mq.findOneAndRemove(conditions, options, callback);
- };
-
-
-
- Model.findByIdAndRemove = function(id, options, callback) {
- if (arguments.length === 1 && typeof id === 'function') {
- const msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
- + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
- + ' ' + this.modelName + '.findByIdAndRemove(id)\n'
- + ' ' + this.modelName + '.findByIdAndRemove()\n';
- throw new TypeError(msg);
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return this.findOneAndRemove({_id: id}, options, callback);
- };
-
-
-
- Model.create = function create(doc, options, callback) {
- let args;
- let cb;
- const discriminatorKey = this.schema.options.discriminatorKey;
-
- if (Array.isArray(doc)) {
- args = doc;
- cb = typeof options === 'function' ? options : callback;
- options = options != null && typeof options === 'object' ? options : {};
- } else {
- const last = arguments[arguments.length - 1];
- options = {};
-
- if (typeof last === 'function' || !last) {
- cb = last;
- args = utils.args(arguments, 0, arguments.length - 1);
- } else {
- args = utils.args(arguments);
- }
- }
-
- if (cb) {
- cb = this.$wrapCallback(cb);
- }
-
- return utils.promiseOrCallback(cb, cb => {
- if (args.length === 0) {
- return cb(null);
- }
-
- const toExecute = [];
- let firstError;
- args.forEach(doc => {
- toExecute.push(callback => {
- const Model = this.discriminators && doc[discriminatorKey] != null ?
- this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this, doc[discriminatorKey]) :
- this;
- if (Model == null) {
- throw new Error(`Discriminator "${doc[discriminatorKey]}" not ` +
- `found for model "${this.modelName}"`);
- }
- let toSave = doc;
- const callbackWrapper = (error, doc) => {
- if (error) {
- if (!firstError) {
- firstError = error;
- }
- return callback(null, { error: error });
- }
- callback(null, { doc: doc });
- };
-
- if (!(toSave instanceof Model)) {
- try {
- toSave = new Model(toSave);
- } catch (error) {
- return callbackWrapper(error);
- }
- }
-
- toSave.save(options, callbackWrapper);
- });
- });
-
- parallel(toExecute, (error, res) => {
- const savedDocs = [];
- const len = res.length;
- for (let i = 0; i < len; ++i) {
- if (res[i].doc) {
- savedDocs.push(res[i].doc);
- }
- }
-
- if (firstError) {
- return cb(firstError, savedDocs);
- }
-
- if (doc instanceof Array) {
- cb(null, savedDocs);
- } else {
- cb.apply(this, [null].concat(savedDocs));
- }
- });
- }, this.events);
- };
-
-
-
- Model.watch = function(pipeline, options) {
- return new ChangeStream(this, pipeline, options);
- };
-
-
-
- Model.startSession = function() {
- return this.db.startSession.apply(this.db, arguments);
- };
-
-
-
- Model.insertMany = function(arr, options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = null;
- }
- return utils.promiseOrCallback(callback, cb => {
- this.$__insertMany(arr, options, cb);
- }, this.events);
- };
-
-
-
- Model.$__insertMany = function(arr, options, callback) {
- const _this = this;
- if (typeof options === 'function') {
- callback = options;
- options = null;
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
- callback = callback || utils.noop;
- options = options || {};
- const limit = get(options, 'limit', 1000);
- const rawResult = get(options, 'rawResult', false);
- const ordered = get(options, 'ordered', true);
-
- if (!Array.isArray(arr)) {
- arr = [arr];
- }
-
- const toExecute = [];
- const validationErrors = [];
- arr.forEach(function(doc) {
- toExecute.push(function(callback) {
- if (!(doc instanceof _this)) {
- doc = new _this(doc);
- }
- doc.validate({ __noPromise: true }, function(error) {
- if (error) {
-
-
-
- if (ordered === false) {
- validationErrors.push(error);
- return callback(null, null);
- }
- return callback(error);
- }
- callback(null, doc);
- });
- });
- });
-
- parallelLimit(toExecute, limit, function(error, docs) {
- if (error) {
- callback(error, null);
- return;
- }
-
- const docAttributes = docs.filter(function(doc) {
- return doc != null;
- });
-
- if (docAttributes.length < 1) {
- callback(null, []);
- return;
- }
- const docObjects = docAttributes.map(function(doc) {
- if (doc.schema.options.versionKey) {
- doc[doc.schema.options.versionKey] = 0;
- }
- if (doc.initializeTimestamps) {
- return doc.initializeTimestamps().toObject(internalToObjectOptions);
- }
- return doc.toObject(internalToObjectOptions);
- });
-
- _this.collection.insertMany(docObjects, options, function(error, res) {
- if (error) {
- callback(error, null);
- return;
- }
- for (let i = 0; i < docAttributes.length; ++i) {
- docAttributes[i].isNew = false;
- docAttributes[i].emit('isNew', false);
- docAttributes[i].constructor.emit('isNew', false);
- }
- if (rawResult) {
- if (ordered === false) {
-
-
- res.mongoose = {
- validationErrors: validationErrors
- };
- }
- return callback(null, res);
- }
- callback(null, docAttributes);
- });
- });
- };
-
-
-
- Model.bulkWrite = function(ops, options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = null;
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
- options = options || {};
-
- const validations = ops.map(op => castBulkWrite(this, op));
-
- return utils.promiseOrCallback(callback, cb => {
- parallel(validations, error => {
- if (error) {
- return cb(error);
- }
-
- this.collection.bulkWrite(ops, options, (error, res) => {
- if (error) {
- return cb(error);
- }
-
- cb(null, res);
- });
- });
- }, this.events);
- };
-
-
-
- Model.hydrate = function(obj) {
- const model = require('./queryhelpers').createModel(this, obj);
- model.init(obj);
- return model;
- };
-
-
-
- Model.update = function update(conditions, doc, options, callback) {
- return _update(this, 'update', conditions, doc, options, callback);
- };
-
-
-
- Model.updateMany = function updateMany(conditions, doc, options, callback) {
- return _update(this, 'updateMany', conditions, doc, options, callback);
- };
-
-
-
- Model.updateOne = function updateOne(conditions, doc, options, callback) {
- return _update(this, 'updateOne', conditions, doc, options, callback);
- };
-
-
-
- Model.replaceOne = function replaceOne(conditions, doc, options, callback) {
- const versionKey = get(this, 'schema.options.versionKey', null);
- if (versionKey && !doc[versionKey]) {
- doc[versionKey] = 0;
- }
-
- return _update(this, 'replaceOne', conditions, doc, options, callback);
- };
-
-
-
- function _update(model, op, conditions, doc, options, callback) {
- const mq = new model.Query({}, {}, model, model.collection);
- if (callback) {
- callback = model.$wrapCallback(callback);
- }
-
-
- if (conditions instanceof Document) {
- conditions = conditions.toObject();
- } else {
- conditions = utils.clone(conditions);
- }
- options = typeof options === 'function' ? options : utils.clone(options);
-
- const versionKey = get(model, 'schema.options.versionKey', null);
- _decorateUpdateWithVersionKey(doc, options, versionKey);
-
- return mq[op](conditions, doc, options, callback);
- }
-
- /**
- * Executes a mapReduce command.
- *
- * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. See [node-mongodb-native mapReduce() documentation](http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#mapreduce) for more detail about options.
- *
- * This function does not trigger any middleware.
- *
- * ####Example:
- *
- * var o = {};
- *
- *
- * o.map = function () { emit(this.name, 1) };
- * o.reduce = function (k, vals) { return vals.length };
- * User.mapReduce(o, function (err, results) {
- * console.log(results)
- * })
- *
- * ####Other options:
- *
- * - `query` {Object} query filter object.
- * - `sort` {Object} sort input objects using this key
- * - `limit` {Number} max number of documents
- * - `keeptemp` {Boolean, default:false} keep temporary data
- * - `finalize` {Function} finalize function
- * - `scope` {Object} scope variables exposed to map/reduce/finalize during execution
- * - `jsMode` {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
- * - `verbose` {Boolean, default:false} provide statistics on job execution time.
- * - `readPreference` {String}
- * - `out*` {Object, default: {inline:1}} sets the output target for the map reduce job.
- *
- * ####* out options:
- *
- * - `{inline:1}` the results are returned in an array
- * - `{replace: 'collectionName'}` add the results to collectionName: the results replace the collection
- * - `{reduce: 'collectionName'}` add the results to collectionName: if dups are detected, uses the reducer / finalize functions
- * - `{merge: 'collectionName'}` add the results to collectionName: if dups exist the new docs overwrite the old
- *
- * If `options.out` is set to `replace`, `merge`, or `reduce`, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the `lean` option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).
- *
- * ####Example:
- *
- * var o = {};
- *
- *
- * o.map = 'function () { emit(this.name, 1) }';
- * o.reduce = 'function (k, vals) { return vals.length }';
- * o.out = { replace: 'createdCollectionNameForResults' }
- * o.verbose = true;
- *
- * User.mapReduce(o, function (err, model, stats) {
- * console.log('map reduce took %d ms', stats.processtime)
- * model.find().where('value').gt(10).exec(function (err, docs) {
- * console.log(docs);
- * });
- * })
- *
- *
- *
- * o.resolveToObject = true;
- * var promise = User.mapReduce(o);
- * promise.then(function (res) {
- * var model = res.model;
- * var stats = res.stats;
- * console.log('map reduce took %d ms', stats.processtime)
- * return model.find().where('value').gt(10).exec();
- * }).then(function (docs) {
- * console.log(docs);
- * }).then(null, handleError).end()
- *
- * @param {Object} o an object specifying map-reduce options
- * @param {Function} [callback] optional callback
- * @see http:
- * @return {Promise}
- * @api public
- */
-
- Model.mapReduce = function mapReduce(o, callback) {
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
- return utils.promiseOrCallback(callback, cb => {
- if (!Model.mapReduce.schema) {
- const opts = {noId: true, noVirtualId: true, strict: false};
- Model.mapReduce.schema = new Schema({}, opts);
- }
-
- if (!o.out) o.out = {inline: 1};
- if (o.verbose !== false) o.verbose = true;
-
- o.map = String(o.map);
- o.reduce = String(o.reduce);
-
- if (o.query) {
- let q = new this.Query(o.query);
- q.cast(this);
- o.query = q._conditions;
- q = undefined;
- }
-
- this.collection.mapReduce(null, null, o, (err, res) => {
- if (err) {
- return cb(err);
- }
- if (res.collection) {
- // returned a collection, convert to Model
- const model = Model.compile('_mapreduce_' + res.collection.collectionName,
- Model.mapReduce.schema, res.collection.collectionName, this.db,
- this.base);
-
- model._mapreduce = true;
- res.model = model;
-
- return cb(null, res);
- }
-
- cb(null, res);
- });
- }, this.events);
- };
-
- /**
- * Performs [aggregations](http:
- *
- * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned.
- *
- * This function triggers the following middleware.
- *
- * - `aggregate()`
- *
- * ####Example:
- *
- * // Find the max balance of all accounts
- * Users.aggregate([
- * { $group: { _id: null, maxBalance: { $max: '$balance' }}},
- * { $project: { _id: 0, maxBalance: 1 }}
- * ]).
- * then(function (res) {
- * console.log(res);
- * });
- *
- *
- * Users.aggregate().
- * group({ _id: null, maxBalance: { $max: '$balance' } }).
- * project('-id maxBalance').
- * exec(function (err, res) {
- * if (err) return handleError(err);
- * console.log(res);
- * });
- *
- * ####NOTE:
- *
- * - Arguments are not cast to the model's schema because `$project` operators allow redefining the "shape" of the documents at any stage of the pipeline, which may leave documents in an incompatible format.
- * - The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
- * - Requires MongoDB >= 2.1
- *
- * @see Aggregate #aggregate_Aggregate
- * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
- * @param {Array} [pipeline] aggregation pipeline as an array of objects
- * @param {Function} [callback]
- * @return {Aggregate}
- * @api public
- */
-
- Model.aggregate = function aggregate(pipeline, callback) {
- if (arguments.length > 2 || get(pipeline, 'constructor.name') === 'Object') {
- throw new Error('Mongoose 5.x disallows passing a spread of operators ' +
- 'to `Model.aggregate()`. Instead of ' +
- '`Model.aggregate({ $match }, { $skip })`, do ' +
- '`Model.aggregate([{ $match }, { $skip }])`');
- }
-
- if (typeof pipeline === 'function') {
- callback = pipeline;
- pipeline = [];
- }
-
- const aggregate = new Aggregate(pipeline || []);
- aggregate.model(this);
-
- if (typeof callback === 'undefined') {
- return aggregate;
- }
-
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- aggregate.exec(callback);
- return aggregate;
- };
-
-
-
- Model.geoSearch = function(conditions, options, callback) {
- if (typeof options === 'function') {
- callback = options;
- options = {};
- }
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
- return utils.promiseOrCallback(callback, cb => {
- let error;
- if (conditions === undefined || !utils.isObject(conditions)) {
- error = new Error('Must pass conditions to geoSearch');
- } else if (!options.near) {
- error = new Error('Must specify the near option in geoSearch');
- } else if (!Array.isArray(options.near)) {
- error = new Error('near option must be an array [x, y]');
- }
-
- if (error) {
- return cb(error);
- }
-
-
- options.search = conditions;
-
- this.collection.geoHaystackSearch(options.near[0], options.near[1], options, (err, res) => {
- if (err) {
- return cb(err);
- }
-
- let count = res.results.length;
- if (options.lean || count === 0) {
- return cb(null, res.results);
- }
-
- const errSeen = false;
-
- function init(err) {
- if (err && !errSeen) {
- return cb(err);
- }
-
- if (!--count && !errSeen) {
- cb(null, res.results);
- }
- }
-
- for (let i = 0; i < res.results.length; ++i) {
- const temp = res.results[i];
- res.results[i] = new this();
- res.results[i].init(temp, {}, init);
- }
- });
- }, this.events);
- };
-
-
-
- Model.populate = function(docs, paths, callback) {
- const _this = this;
- if (callback) {
- callback = this.$wrapCallback(callback);
- }
-
-
- paths = utils.populate(paths);
-
-
- const cache = {};
-
- return utils.promiseOrCallback(callback, cb => {
- _populate(_this, docs, paths, cache, cb);
- }, this.events);
- };
-
-
-
- function _populate(model, docs, paths, cache, callback) {
- let pending = paths.length;
-
- if (pending === 0) {
- return callback(null, docs);
- }
-
-
- let i = pending;
- let path;
- while (i--) {
- path = paths[i];
- populate(model, docs, path, next);
- }
-
- function next(err) {
- if (err) {
- return callback(err, null);
- }
- if (--pending) {
- return;
- }
- callback(null, docs);
- }
- }
-
-
- const excludeIdReg = /\s?-_id\s?/;
- const excludeIdRegGlobal = /\s?-_id\s?/g;
-
- function populate(model, docs, options, callback) {
-
- if (!Array.isArray(docs)) {
- docs = [docs];
- }
-
- if (docs.length === 0 || docs.every(utils.isNullOrUndefined)) {
- return callback();
- }
-
- const modelsMap = getModelsMapForPopulate(model, docs, options);
-
- if (modelsMap instanceof Error) {
- return immediate(function() {
- callback(modelsMap);
- });
- }
-
- const len = modelsMap.length;
- let mod;
- let match;
- let select;
- let vals = [];
-
- function flatten(item) {
-
- return undefined !== item;
- }
-
- let _remaining = len;
- let hasOne = false;
- for (let i = 0; i < len; ++i) {
- mod = modelsMap[i];
- select = mod.options.select;
-
- if (mod.options.match) {
- match = utils.object.shallowCopy(mod.options.match);
- } else if (get(mod, 'options.options.match')) {
- match = utils.object.shallowCopy(mod.options.options.match);
- delete mod.options.options.match;
- } else {
- match = {};
- }
-
- let ids = utils.array.flatten(mod.ids, flatten);
- ids = utils.array.unique(ids);
-
- if (ids.length === 0 || ids.every(utils.isNullOrUndefined)) {
- --_remaining;
- continue;
- }
-
- hasOne = true;
- if (mod.foreignField.size === 1) {
- const foreignField = Array.from(mod.foreignField)[0];
- if (foreignField !== '_id' || !match['_id']) {
- match[foreignField] = { $in: ids };
- }
- } else {
- match.$or = [];
- for (const foreignField of mod.foreignField) {
- if (foreignField !== '_id' || !match['_id']) {
- match.$or.push({ [foreignField]: { $in: ids } });
- }
- }
- }
-
- const assignmentOpts = {};
- assignmentOpts.sort = get(mod, 'options.options.sort', void 0);
- assignmentOpts.excludeId = excludeIdReg.test(select) || (select && select._id === 0);
-
- if (assignmentOpts.excludeId) {
-
-
-
- if (typeof select === 'string') {
- select = select.replace(excludeIdRegGlobal, ' ');
- } else {
-
- select = utils.object.shallowCopy(select);
- delete select._id;
- }
- }
-
-
- if (mod.count) {
- mod.model.countDocuments(match, function(err, count) {
- if (err != null) {
- return callback(err);
- }
-
- for (const doc of docs) {
- try {
- if (doc.$__ != null) {
- doc.set(mod.options.path, count);
- } else {
- utils.setValue(mod.options.path, count, doc);
- }
- } catch (err) {
- return callback(err);
- }
- }
-
- callback(null);
- });
- continue;
- }
-
- if (mod.options.options && mod.options.options.limit) {
- assignmentOpts.originalLimit = mod.options.options.limit;
- mod.options.options.limit = mod.options.options.limit * ids.length;
- }
-
- const subPopulate = utils.clone(mod.options.populate);
-
- const query = mod.model.find(match, select, mod.options.options);
-
-
-
-
-
- for (const foreignField of mod.foreignField) {
- if (foreignField !== '_id' && query.selectedInclusively() &&
- !isPathSelectedInclusive(query._fields, foreignField)) {
- query.select(foreignField);
- }
- }
-
-
- if (subPopulate) {
- query.populate(subPopulate);
- }
-
- query.exec(next.bind(this, mod, assignmentOpts));
- }
-
- if (!hasOne) {
- return callback();
- }
-
- function next(options, assignmentOpts, err, valsFromDb) {
- if (mod.options.options && mod.options.options.limit) {
- mod.options.options.limit = assignmentOpts.originalLimit;
- }
-
- if (err) return callback(err, null);
- vals = vals.concat(valsFromDb);
- _assign(null, vals, options, assignmentOpts);
- if (--_remaining === 0) {
- callback();
- }
- }
-
- function _assign(err, vals, mod, assignmentOpts) {
- if (err) {
- return callback(err, null);
- }
-
- const options = mod.options;
- const isVirtual = mod.isVirtual;
- const justOne = mod.justOne;
- let _val;
- const lean = options.options && options.options.lean;
- const len = vals.length;
- const rawOrder = {};
- const rawDocs = {};
- let key;
- let val;
-
-
- const allIds = utils.clone(mod.allIds);
-
-
-
-
- for (let i = 0; i < len; i++) {
- val = vals[i];
- if (val == null) {
- continue;
- }
- for (const foreignField of mod.foreignField) {
- _val = utils.getValue(foreignField, val);
- if (Array.isArray(_val)) {
- const _valLength = _val.length;
- for (let j = 0; j < _valLength; ++j) {
- let __val = _val[j];
- if (__val instanceof Document) {
- __val = __val._id;
- }
- key = String(__val);
- if (rawDocs[key]) {
- if (Array.isArray(rawDocs[key])) {
- rawDocs[key].push(val);
- rawOrder[key].push(i);
- } else {
- rawDocs[key] = [rawDocs[key], val];
- rawOrder[key] = [rawOrder[key], i];
- }
- } else {
- if (isVirtual && !justOne) {
- rawDocs[key] = [val];
- rawOrder[key] = [i];
- } else {
- rawDocs[key] = val;
- rawOrder[key] = i;
- }
- }
- }
- } else {
- if (_val instanceof Document) {
- _val = _val._id;
- }
- key = String(_val);
- if (rawDocs[key]) {
- if (Array.isArray(rawDocs[key])) {
- rawDocs[key].push(val);
- rawOrder[key].push(i);
- } else {
- rawDocs[key] = [rawDocs[key], val];
- rawOrder[key] = [rawOrder[key], i];
- }
- } else {
- rawDocs[key] = val;
- rawOrder[key] = i;
- }
- }
-
- if (lean) {
- leanPopulateMap.set(val, mod.model);
- } else {
- val.$__.wasPopulated = true;
- }
- }
- }
-
- assignVals({
- originalModel: model,
-
- rawIds: mod.isVirtual ? allIds : mod.allIds,
- allIds: allIds,
- foreignField: mod.foreignField,
- rawDocs: rawDocs,
- rawOrder: rawOrder,
- docs: mod.docs,
- path: options.path,
- options: assignmentOpts,
- justOne: mod.justOne,
- isVirtual: mod.isVirtual,
- allOptions: mod,
- lean: lean,
- virtual: mod.virtual
- });
- }
- }
-
-
-
- function assignVals(o) {
-
- const userOptions = get(o, 'allOptions.options.options');
- // `o.options` contains options explicitly listed in `populateOptions`, like
- // `match` and `limit`.
- const populateOptions = Object.assign({}, o.options, userOptions, {
- justOne: o.justOne
- });
-
-
-
- assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, populateOptions);
-
-
-
- const docs = o.docs;
- const rawIds = o.rawIds;
- const options = o.options;
-
- function setValue(val) {
- return valueFilter(val, options, populateOptions);
- }
-
- for (let i = 0; i < docs.length; ++i) {
- const existingVal = utils.getValue(o.path, docs[i]);
- if (existingVal == null && !getVirtual(o.originalModel.schema, o.path)) {
- continue;
- }
-
-
-
- const originalSchema = o.originalModel.schema;
- let isMap = isModel(docs[i]) ?
- existingVal instanceof Map :
- utils.isPOJO(existingVal);
-
-
- isMap = isMap && get(originalSchema._getSchema(o.path), '$isSchemaMap');
- if (!o.isVirtual && isMap) {
- const _keys = existingVal instanceof Map ?
- Array.from(existingVal.keys()) :
- Object.keys(existingVal);
- rawIds[i] = rawIds[i].reduce((cur, v, i) => {
-
- cur.$init(_keys[i], v);
- return cur;
- }, new MongooseMap({}, docs[i]));
- }
-
- if (o.isVirtual && docs[i] instanceof Model) {
-
-
- mpath.set(o.path, rawIds[i], docs[i], setValue);
- continue;
- }
-
- const parts = o.path.split('.');
- let cur = docs[i];
- for (let j = 0; j < parts.length - 1; ++j) {
- if (cur[parts[j]] == null) {
- cur[parts[j]] = {};
- }
- cur = cur[parts[j]];
- }
- if (docs[i].$__) {
- docs[i].populated(o.path, o.allIds[i], o.allOptions);
- }
-
-
-
-
- utils.setValue(o.path, rawIds[i], docs[i], function(v) {
- if (o.justOne === true && Array.isArray(v)) {
- return setValue(v[0]);
- } else if (o.justOne === false && !Array.isArray(v)) {
- return setValue([v]);
- }
- return setValue(v);
- }, false);
- }
- }
-
-
-
- function isModel(obj) {
- return get(obj, '$__') != null;
- }
-
- function getModelsMapForPopulate(model, docs, options) {
- let i;
- let doc;
- const len = docs.length;
- const available = {};
- const map = [];
- const modelNameFromQuery = options.model && options.model.modelName || options.model;
- let schema;
- let refPath;
- let Model;
- let currentOptions;
- let modelNames;
- let modelName;
- let discriminatorKey;
- let modelForFindSchema;
-
- const originalModel = options.model;
- let isVirtual = false;
- const modelSchema = model.schema;
-
- for (i = 0; i < len; i++) {
- doc = docs[i];
-
- schema = getSchemaTypes(modelSchema, doc, options.path);
- const isUnderneathDocArray = schema && schema.$isUnderneathDocArray;
- if (isUnderneathDocArray && get(options, 'options.sort') != null) {
- return new Error('Cannot populate with `sort` on path ' + options.path +
- ' because it is a subproperty of a document array');
- }
-
- modelNames = null;
- let isRefPath = false;
- if (Array.isArray(schema)) {
- for (let j = 0; j < schema.length; ++j) {
- let _modelNames;
- try {
- const res = _getModelNames(doc, schema[j]);
- _modelNames = res.modelNames;
- isRefPath = res.isRefPath;
- } catch (error) {
- return error;
- }
- if (!_modelNames) {
- continue;
- }
- modelNames = modelNames || [];
- for (let x = 0; x < _modelNames.length; ++x) {
- if (modelNames.indexOf(_modelNames[x]) === -1) {
- modelNames.push(_modelNames[x]);
- }
- }
- }
- } else {
- try {
- const res = _getModelNames(doc, schema);
- modelNames = res.modelNames;
- isRefPath = res.isRefPath;
- } catch (error) {
- return error;
- }
-
- if (!modelNames) {
- continue;
- }
- }
-
- const virtual = getVirtual(model.schema, options.path);
- let localField;
- let count = false;
- if (virtual && virtual.options) {
- const virtualPrefix = virtual.$nestedSchemaPath ?
- virtual.$nestedSchemaPath + '.' : '';
- if (typeof virtual.options.localField === 'function') {
- localField = virtualPrefix + virtual.options.localField.call(doc, doc);
- } else {
- localField = virtualPrefix + virtual.options.localField;
- }
- count = virtual.options.count;
- } else {
- localField = options.path;
- }
- let foreignField = virtual && virtual.options ?
- virtual.options.foreignField :
- '_id';
-
-
-
-
- let justOne = null;
- if ('justOne' in options) {
- justOne = options.justOne;
- } else if (virtual && virtual.options && virtual.options.ref) {
- let normalizedRef;
- if (typeof virtual.options.ref === 'function') {
- normalizedRef = virtual.options.ref.call(doc, doc);
- } else {
- normalizedRef = virtual.options.ref;
- }
- justOne = !!virtual.options.justOne;
- isVirtual = true;
- if (!modelNames) {
- modelNames = [].concat(normalizedRef);
- }
- } else if (schema && !schema[schemaMixedSymbol]) {
-
- justOne = !schema.$isMongooseArray;
- }
-
- if (!modelNames) {
- continue;
- }
-
- if (virtual && (!localField || !foreignField)) {
- return new Error('If you are populating a virtual, you must set the ' +
- 'localField and foreignField options');
- }
-
- options.isVirtual = isVirtual;
- options.virtual = virtual;
- if (typeof localField === 'function') {
- localField = localField.call(doc, doc);
- }
- if (typeof foreignField === 'function') {
- foreignField = foreignField.call(doc);
- }
-
- const localFieldPath = modelSchema.paths[localField];
- const localFieldGetters = localFieldPath ? localFieldPath.getters : [];
- let ret;
-
- const _populateOptions = get(options, 'options', {});
-
- const getters = 'getters' in _populateOptions ?
- _populateOptions.getters :
- options.isVirtual && get(virtual, 'options.getters', false);
- if (localFieldGetters.length > 0 && getters) {
- const hydratedDoc = (doc.$__ != null) ? doc : model.hydrate(doc);
- ret = localFieldPath.applyGetters(doc[localField], hydratedDoc);
- } else {
- ret = convertTo_id(utils.getValue(localField, doc));
- }
-
- const id = String(utils.getValue(foreignField, doc));
- options._docs[id] = Array.isArray(ret) ? ret.slice() : ret;
-
- let k = modelNames.length;
- while (k--) {
- modelName = modelNames[k];
- if (modelName == null) {
- continue;
- }
-
- try {
- Model = originalModel && originalModel[modelSymbol] ?
- originalModel :
- modelName[modelSymbol] ? modelName : model.db.model(modelName);
- } catch (error) {
- return error;
- }
-
- let ids = ret;
- const flat = Array.isArray(ret) ? utils.array.flatten(ret) : [];
- if (isRefPath && Array.isArray(ret) && flat.length === modelNames.length) {
- ids = flat.filter((val, i) => modelNames[i] === modelName);
- }
-
- if (!available[modelName]) {
- currentOptions = {
- model: Model
- };
-
- if (isVirtual && virtual.options && virtual.options.options) {
- currentOptions.options = utils.clone(virtual.options.options);
- }
- utils.merge(currentOptions, options);
- if (schema && !discriminatorKey) {
- currentOptions.model = Model;
- }
- options.model = Model;
-
- available[modelName] = {
- model: Model,
- options: currentOptions,
- docs: [doc],
- ids: [ids],
- allIds: [ret],
- localField: new Set([localField]),
- foreignField: new Set([foreignField]),
- justOne: justOne,
- isVirtual: isVirtual,
- virtual: virtual,
- count: count
- };
- map.push(available[modelName]);
- } else {
- available[modelName].localField.add(localField);
- available[modelName].foreignField.add(foreignField);
- available[modelName].docs.push(doc);
- available[modelName].ids.push(ids);
- available[modelName].allIds.push(ret);
- }
- }
- }
-
- function _getModelNames(doc, schema) {
- let modelNames;
- let discriminatorKey;
- let isRefPath = false;
-
- if (schema && schema.caster) {
- schema = schema.caster;
- }
- if (schema && schema.$isSchemaMap) {
- schema = schema.$__schemaType;
- }
-
- if (!schema && model.discriminators) {
- discriminatorKey = model.schema.discriminatorMapping.key;
- }
-
- refPath = schema && schema.options && schema.options.refPath;
-
- const normalizedRefPath = normalizeRefPath(refPath, doc, options.path);
-
- if (modelNameFromQuery) {
- modelNames = [modelNameFromQuery];
- } else if (normalizedRefPath) {
- if (options._queryProjection != null && isPathExcluded(options._queryProjection, normalizedRefPath)) {
- throw new Error('refPath `' + normalizedRefPath +
- '` must not be excluded in projection, got ' +
- util.inspect(options._queryProjection));
- }
- modelNames = utils.getValue(normalizedRefPath, doc);
- if (Array.isArray(modelNames)) {
- modelNames = utils.array.flatten(modelNames);
- }
-
- isRefPath = true;
- } else {
- let modelForCurrentDoc = model;
- let schemaForCurrentDoc;
-
- if (!schema && discriminatorKey) {
- modelForFindSchema = utils.getValue(discriminatorKey, doc);
-
- if (modelForFindSchema) {
- try {
- modelForCurrentDoc = model.db.model(modelForFindSchema);
- } catch (error) {
- return error;
- }
-
- schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
-
- if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
- schemaForCurrentDoc = schemaForCurrentDoc.caster;
- }
- }
- } else {
- schemaForCurrentDoc = schema;
- }
- const virtual = getVirtual(modelForCurrentDoc.schema, options.path);
-
- let ref;
- if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) {
- modelNames = [ref];
- } else if ((ref = get(virtual, 'options.ref')) != null) {
- if (typeof ref === 'function') {
- ref = ref.call(doc, doc);
- }
-
-
-
- if (Array.isArray(ref)) {
- modelNames = ref;
- } else {
- modelNames = [ref];
- }
-
- isVirtual = true;
- } else {
-
-
- modelNames = discriminatorKey ? null : [model.modelName];
- }
- }
-
- if (!modelNames) {
- return { modelNames: modelNames, isRefPath: isRefPath };
- }
-
- if (!Array.isArray(modelNames)) {
- modelNames = [modelNames];
- }
-
- return { modelNames: modelNames, isRefPath: isRefPath };
- }
-
- return map;
- }
-
-
-
- function convertTo_id(val) {
- if (val instanceof Model) return val._id;
-
- if (Array.isArray(val)) {
- for (let i = 0; i < val.length; ++i) {
- if (val[i] instanceof Model) {
- val[i] = val[i]._id;
- }
- }
- if (val.isMongooseArray && val._schema) {
- return val._schema.cast(val, val._parent);
- }
-
- return [].concat(val);
- }
-
-
-
- if (val != null && val.constructor.name === 'Object') {
- const ret = [];
- for (const key of Object.keys(val)) {
- ret.push(val[key]);
- }
- return ret;
- }
-
-
- if (val instanceof Map) {
- return Array.from(val.values());
- }
-
- return val;
- }
-
-
-
- function valueFilter(val, assignmentOpts, populateOptions) {
- if (Array.isArray(val)) {
-
- const ret = [];
- const numValues = val.length;
- for (let i = 0; i < numValues; ++i) {
- const subdoc = val[i];
- if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null)) {
- continue;
- }
- maybeRemoveId(subdoc, assignmentOpts);
- ret.push(subdoc);
- if (assignmentOpts.originalLimit &&
- ret.length >= assignmentOpts.originalLimit) {
- break;
- }
- }
-
-
-
- while (val.length > ret.length) {
- Array.prototype.pop.apply(val, []);
- }
- for (let i = 0; i < ret.length; ++i) {
- val[i] = ret[i];
- }
- return val;
- }
-
-
- if (isPopulatedObject(val)) {
- maybeRemoveId(val, assignmentOpts);
- return val;
- }
-
- if (populateOptions.justOne === true) {
- return (val == null ? val : null);
- }
- if (populateOptions.justOne === false) {
- return [];
- }
- return val;
- }
-
-
-
- function maybeRemoveId(subdoc, assignmentOpts) {
- if (assignmentOpts.excludeId) {
- if (typeof subdoc.setValue === 'function') {
- delete subdoc._doc._id;
- } else {
- delete subdoc._id;
- }
- }
- }
-
-
-
- function isPopulatedObject(obj) {
- if (obj == null) {
- return false;
- }
-
- return Array.isArray(obj) ||
- obj.$isMongooseMap ||
- obj.$__ != null ||
- leanPopulateMap.has(obj);
- }
-
-
-
- Model.compile = function compile(name, schema, collectionName, connection, base) {
- const versioningEnabled = schema.options.versionKey !== false;
-
- setParentPointers(schema);
-
- if (versioningEnabled && !schema.paths[schema.options.versionKey]) {
-
- const o = {};
- o[schema.options.versionKey] = Number;
- schema.add(o);
- }
-
- let model;
- if (typeof name === 'function' && name.prototype instanceof Model) {
- model = name;
- name = model.name;
- schema.loadClass(model, false);
- model.prototype.$isMongooseModelPrototype = true;
- } else {
-
- model = function model(doc, fields, skipId) {
- model.hooks.execPreSync('createModel', doc);
- if (!(this instanceof model)) {
- return new model(doc, fields, skipId);
- }
- Model.call(this, doc, fields, skipId);
- };
- }
-
- model.hooks = schema.s.hooks.clone();
- model.base = base;
- model.modelName = name;
-
- if (!(model.prototype instanceof Model)) {
- model.__proto__ = Model;
- model.prototype.__proto__ = Model.prototype;
- }
- model.model = Model.prototype.model;
- model.db = model.prototype.db = connection;
- model.discriminators = model.prototype.discriminators = undefined;
- model[modelSymbol] = true;
- model.events = new EventEmitter();
-
- model.prototype.$__setSchema(schema);
-
- const _userProvidedOptions = schema._userProvidedOptions || {};
-
-
- let bufferCommands = true;
-
- if (connection.base.get('bufferCommands') != null) {
- bufferCommands = connection.base.get('bufferCommands');
- }
-
- if (connection.config.bufferCommands != null) {
- bufferCommands = connection.config.bufferCommands;
- }
-
- if (_userProvidedOptions.bufferCommands != null) {
- bufferCommands = _userProvidedOptions.bufferCommands;
- }
-
- const collectionOptions = {
- bufferCommands: bufferCommands,
- capped: schema.options.capped
- };
-
- model.prototype.collection = connection.collection(
- collectionName,
- collectionOptions
- );
- model.prototype[modelCollectionSymbol] = model.prototype.collection;
-
-
- applyMethods(model, schema);
- applyStatics(model, schema);
- applyHooks(model, schema);
-
- model.schema = model.prototype.schema;
- model.collection = model.prototype.collection;
-
-
- model.Query = function() {
- Query.apply(this, arguments);
- };
- model.Query.prototype = Object.create(Query.prototype);
- model.Query.base = Query.base;
- applyQueryMiddleware(model.Query, model);
- applyQueryMethods(model, schema.query);
-
- const kareemOptions = {
- useErrorHandlers: true,
- numCallbackParams: 1
- };
- model.$__insertMany = model.hooks.createWrapper('insertMany',
- model.$__insertMany, model, kareemOptions);
-
- return model;
- };
-
-
-
- function applyQueryMethods(model, methods) {
- for (const i in methods) {
- model.Query.prototype[i] = methods[i];
- }
- }
-
-
-
- Model.__subclass = function subclass(conn, schema, collection) {
-
- const _this = this;
-
- const Model = function Model(doc, fields, skipId) {
- if (!(this instanceof Model)) {
- return new Model(doc, fields, skipId);
- }
- _this.call(this, doc, fields, skipId);
- };
-
- Model.__proto__ = _this;
- Model.prototype.__proto__ = _this.prototype;
- Model.db = Model.prototype.db = conn;
-
- const s = schema && typeof schema !== 'string'
- ? schema
- : _this.prototype.schema;
-
- const options = s.options || {};
- const _userProvidedOptions = s._userProvidedOptions || {};
-
- if (!collection) {
- collection = _this.prototype.schema.get('collection') ||
- utils.toCollectionName(_this.modelName, this.base.pluralize());
- }
-
- let bufferCommands = true;
- if (s) {
- if (conn.config.bufferCommands != null) {
- bufferCommands = conn.config.bufferCommands;
- }
- if (_userProvidedOptions.bufferCommands != null) {
- bufferCommands = _userProvidedOptions.bufferCommands;
- }
- }
- const collectionOptions = {
- bufferCommands: bufferCommands,
- capped: s && options.capped
- };
-
- Model.prototype.collection = conn.collection(collection, collectionOptions);
- Model.prototype[modelCollectionSymbol] = Model.prototype.collection;
- Model.collection = Model.prototype.collection;
-
- Model.init(() => {});
- return Model;
- };
-
- Model.$wrapCallback = function(callback) {
- if (callback == null) {
- return callback;
- }
- if (typeof callback !== 'function') {
- throw new Error('Callback must be a function, got ' + callback);
- }
- const _this = this;
- return function() {
- try {
- callback.apply(null, arguments);
- } catch (error) {
- _this.emit('error', error);
- }
- };
- };
-
-
-
- module.exports = exports = Model;
|