diff --git a/.eslintrc.json b/.eslintrc.json index 589be0e1799..c9747d96875 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,6 +25,7 @@ "rules": { "@typescript-eslint/triple-slash-reference": "off", "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-empty-function": "off", "spaced-comment": [ "error", "always", diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 3089b69e90e..5e6d4c2f340 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,4 +1,4 @@ -name: 🪲 Bug report +name: 🐛 Bug report description: Create a report to help us improve body: @@ -37,6 +37,14 @@ body: validations: required: true + - type: input + id: typescript-version + attributes: + label: Typescript version (if applicable) + placeholder: 4.8.x + validations: + required: false + - type: textarea id: description attributes: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 13df955f303..2bdb2948168 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,8 +6,6 @@ updates: interval: "monthly" open-pull-requests-limit: 100 target-branch: master - ignore: - - dependency-name: "dox" - package-ecosystem: github-actions directory: "/" schedule: diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 3d0f4960ca9..388b9b78a21 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -22,16 +22,16 @@ jobs: runs-on: ubuntu-20.04 name: Benchmark TypeScript Types steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 with: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 16 - run: npm install - - run: npx ts-benchmark -p ./benchmarks/typescript/simple -f 17/100000 18 29 32 -b master -g -t --colors - env: - DB_URL: ${{ secrets.DB_URL }} + - run: node ./scripts/create-tarball.js + + - run: npm run ts-benchmark diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9c78ef14c90..7df61155d4d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 7a63c4fa0fb..8c1f24dae12 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -28,10 +28,10 @@ jobs: runs-on: ubuntu-20.04 name: Test Generating Docs steps: - - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 16 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d41bb668b35..1f035a7d146 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: stale - uses: actions/stale@v5 + uses: actions/stale@v7 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c0510d90d8..6d1c95b790b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,10 +22,10 @@ jobs: runs-on: ubuntu-latest name: Lint JS-Files steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 14 @@ -39,14 +39,14 @@ jobs: strategy: fail-fast: false matrix: - node: [12, 14, 16, 18] + node: [14, 16, 18] os: [ubuntu-18.04, ubuntu-20.04] - mongodb: [4.0.2, 5.0.2, 6.0.0] + mongodb: [4.0.28, 5.0.8, 6.0.0] include: - - os: ubuntu-18.04 - mongodb-os: ubuntu1804 - - os: ubuntu-20.04 - mongodb-os: ubuntu2004 + - os: ubuntu-20.04 # customize on which matrix the coverage will be collected on + mongodb: 5.0.11 + node: 16 + coverage: true exclude: - os: ubuntu-18.04 # exclude because nodejs 18 requires higher GLIBC node: 18 @@ -55,27 +55,64 @@ jobs: - os: ubuntu-20.04 # exclude because there are no <4.4 mongodb builds for 2004 mongodb: 4.0.2 name: Node ${{ matrix.node }} MongoDB ${{ matrix.mongodb }} OS ${{ matrix.os }} + env: + MONGOMS_VERSION: ${{ matrix.mongodb }} + MONGOMS_PREFER_GLOBAL_PATH: 1 steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: ${{ matrix.node }} - - run: npm install + - name: Load MongoDB binary cache + id: cache-mongodb-binaries + uses: actions/cache@v3 + with: + path: ~/.cache/mongodb-binaries + key: ${{ matrix.os }}-${{ matrix.mongodb }} - - name: Setup - run: | - wget -q https://downloads.mongodb.org/linux/mongodb-linux-x86_64-${{ matrix.mongodb-os }}-${{ matrix.mongodb }}.tgz - tar xf mongodb-linux-x86_64-${{ matrix.mongodb-os }}-${{ matrix.mongodb }}.tgz - mkdir -p ./data/db/27017 ./data/db/27000 - printf "\n--timeout 8000" >> ./test/mocha.opts - ./mongodb-linux-x86_64-${{ matrix.mongodb-os }}-${{ matrix.mongodb }}/bin/mongod --setParameter ttlMonitorSleepSecs=1 --fork --dbpath ./data/db/27017 --syslog --port 27017 - sleep 2 - mongod --version - echo `pwd`/mongodb-linux-x86_64-${{ matrix.mongodb-os }}-${{ matrix.mongodb }}/bin >> $GITHUB_PATH - - run: npm test + - run: npm install + - name: NPM Test without Coverage + run: npm test + if: matrix.coverage != true + - name: NPM Test with Coverage + run: npm run test-coverage + if: matrix.coverage == true + - name: Archive code coverage results + uses: actions/upload-artifact@v3 + if: matrix.coverage == true + with: + name: coverage + path: coverage + + test-deno: + runs-on: ubuntu-20.04 + name: Deno tests + env: + MONGOMS_VERSION: 6.0.0 + MONGOMS_PREFER_GLOBAL_PATH: 1 + steps: + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - name: Setup node + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + with: + node-version: 16 + - name: Load MongoDB binary cache + id: cache-mongodb-binaries + uses: actions/cache@v3 + with: + path: ~/.cache/mongodb-binaries + key: deno-${{ env.MONGOMS_VERSION }} + - name: Setup Deno + uses: denoland/setup-deno@v1 + with: + deno-version: v1.30.x + - run: deno --version + - run: npm install + - name: Run Deno tests + run: npm run test-deno test-replica-sets: needs: @@ -83,44 +120,15 @@ jobs: runs-on: ubuntu-latest name: Replica Set tests steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 16 - run: npm install - name: Test run: npm run test-rs - coverage: - needs: - - test-replica-sets - runs-on: ubuntu-20.04 - name: Coverage - steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 - with: - node-version: 16 - - run: npm install - - name: Setup - run: | - wget -q https://downloads.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-5.0.2.tgz - tar xf mongodb-linux-x86_64-ubuntu2004-5.0.2.tgz - mkdir -p ./data/db/27017 ./data/db/27000 - printf "\n--timeout 8000" >> ./test/mocha.opts - ./mongodb-linux-x86_64-ubuntu2004-5.0.2/bin/mongod --setParameter ttlMonitorSleepSecs=1 --fork --dbpath ./data/db/27017 --syslog --port 27017 - sleep 2 - mongod --version - echo `pwd`/mongodb-linux-x86_64-ubuntu2004-5.0.2/bin >> $GITHUB_PATH - - name: test with coverage - run: npm run test-coverage - - name: Archive code coverage results - uses: actions/upload-artifact@v3 - with: - name: coverage - path: coverage dependency-review: name: Dependency Review if: github.event_name == 'pull_request' @@ -129,6 +137,6 @@ jobs: contents: read steps: - name: Check out repo - uses: actions/checkout@v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Dependency review - uses: actions/dependency-review-action@v2 + uses: actions/dependency-review-action@v3 diff --git a/.github/workflows/tidelift-alignment.yml b/.github/workflows/tidelift-alignment.yml index 83b6b6cebeb..b3b245f2248 100644 --- a/.github/workflows/tidelift-alignment.yml +++ b/.github/workflows/tidelift-alignment.yml @@ -15,9 +15,9 @@ jobs: if: github.repository == 'Automattic/mongoose' steps: - name: Checkout - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 16 - name: Alignment diff --git a/.github/workflows/tsd.yml b/.github/workflows/tsd.yml index b55144825d0..2a220877fea 100644 --- a/.github/workflows/tsd.yml +++ b/.github/workflows/tsd.yml @@ -22,10 +22,10 @@ jobs: runs-on: ubuntu-latest name: Lint TS-Files steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 14 @@ -40,14 +40,14 @@ jobs: runs-on: ubuntu-latest name: Test Typescript Types steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Setup node - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # v3.4.1 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: 12 - run: npm install - name: Typings - run: npm run test-tsd \ No newline at end of file + run: npm run test-tsd diff --git a/.gitignore b/.gitignore index 70b24471080..eccf511e6e9 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ coverage npm-debug.log data/ .nyc_output/ +.env tools/31* @@ -56,4 +57,11 @@ index.html # yarn package-lock yarn.lock +# npm pack output +mongoose.tgz +mongoose-*.tgz + examples/ecommerce-netlify-functions/.netlify/state.json + +notes.md +list.out \ No newline at end of file diff --git a/.mocharc.yml b/.mocharc.yml new file mode 100644 index 00000000000..efa9bf8a87b --- /dev/null +++ b/.mocharc.yml @@ -0,0 +1,4 @@ +reporter: spec # better to identify failing / slow tests than "dot" +ui: bdd # explicitly setting, even though it is mocha default +require: + - test/mocha-fixtures.js diff --git a/.npmignore b/.npmignore index 70115377db2..0b04b677a60 100644 --- a/.npmignore +++ b/.npmignore @@ -40,4 +40,9 @@ renovate.json webpack.config.js webpack.base.config.js -.nyc-output \ No newline at end of file +.nyc-output + +*.tgz + +notes.md +list.out \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e8b8b6a242..a85230ab0d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,313 @@ +7.0.0 / 2023-02-27 +================== + * BREAKING CHANGE: copy schema options when merging schemas using new Schema() or Schema.prototype.add() #13092 + * feat(types): export mongodb types more robustly #12948 [simon-abbott](https://github.com/simon-abbott) + * docs: fix populate docs #13090 [hasezoey](https://github.com/hasezoey) + * docs(migrating_to_6): added info about removal of reconnectTries and reconnectInterval options #13083 [lpizzinidev](https://github.com/lpizzinidev) + +7.0.0-rc0 / 2023-02-23 +====================== + * BREAKING CHANGE: remove support for callbacks #11431 + * BREAKING CHANGE: upgrade to MongoDB node driver 5.x, bson 5.x #12955 + * BREAKING CHANGE: make `strictQuery: false` by default #11861 #11807 #11514 + * BREAKING CHANGE: remove support for setting schema path definitions to primitives, except `_id: false` #12832 #7558 [lpizzinidev](https://github.com/lpizzinidev) + * BREAKING CHANGE: discriminator schemas now inherit base schema options by default #12928 #12135 + * BREAKING CHANGE: orFail() now throws on updateOne() and updateMany() if matchedCount === 0, not modifiedCount === 0 #11620 + * BREAKING CHANGE: remove support for custom promise libraries #12878 #12872 [lpizzinidev](https://github.com/lpizzinidev) + * BREAKING CHANGE: select('name -path') behaves as select('name') if path has schema-level select: true #11694 + * BREAKING CHANGE(types): remove support for document interfaces that extends Document #11615 + * BREAKING CHANGE: pluralize 'human' as 'humans', not 'humen' #13037 + * BREAKING CHANGE: renamed schema option supressReservedKeysWarning -> suppressReservedKeysWarning #11495 + * BREAKING CHANGE: remove unused DisconnectedError #13028 [lpizzinidev](https://github.com/lpizzinidev) + * BREAKING CHANGE: remove unsupported query options maxScan and snapshot #13023 #13022 [hasezoey](https://github.com/hasezoey) + +6.10.0 / 2023-02-22 +=================== + * feat: upgrade to mongodb driver 4.14.0 #13036 + * feat: added Schema.prototype.omit() function #12939 #12931 [lpizzinidev](https://github.com/lpizzinidev) + * feat(index): added createInitialConnection option to Mongoose constructor #13021 #12965 [lpizzinidev](https://github.com/lpizzinidev) + +6.9.3 / 2023-02-22 +================== + * fix(connection): delay calculating `autoCreate` and `autoIndex` until after initial connection established #13007 #12940 [lpizzinidev](https://github.com/lpizzinidev) + * fix(discriminator): allows update doc with discriminatorKey #13056 #13055 [abarriel](https://github.com/abarriel) + * fix(query): avoid sending unnecessary empty projection to MongoDB server #13059 #13050 + * fix(model): avoid sending null session option with document operations #13053 #13052 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): use MergeTypes for type overrides in HydratedDocument #13066 #13040 + * docs(middleware): list validate as a potential query middleware #13057 #12680 + * docs(getters-setters): explain that getters do not run by default on toJSON() #13058 #13049 + * docs: refactor docs generation scripts #13044 [hasezoey](https://github.com/hasezoey) + +5.13.16 / 2023-02-20 +==================== + * fix: make access to process.versions lazy #12584 [maciasello](https://github.com/maciasello) + * fix(types): add missing type definitions for `bulkSave()` #12019 + * docs: backport documentation URL updates #12692 [hasezoey](https://github.com/hasezoey) + +6.9.2 / 2023-02-16 +================== + * fix(model): fixed post('save') callback parameter #13030 #13026 [lpizzinidev](https://github.com/lpizzinidev) + * fix(UUID): added null check to prevent error on binaryToString conversion #13034 #13032 #13029 [lpizzinidev](https://github.com/lpizzinidev) [Freezystem](https://github.com/Freezystem) + * fix(query): revert breaking changes introduced by #12797 #12999 [lpizzinidev](https://github.com/lpizzinidev) + * fix(document): make array $shift() use $pop instead of overwriting array #13004 + * docs: update & remove old links #13019 [hasezoey](https://github.com/hasezoey) + * docs(middleware): describe how to access model from document middleware #13031 [AxeOfMen](https://github.com/AxeOfMen) + * docs: update broken & outdated links #13001 [hasezoey](https://github.com/hasezoey) + * chore: change deno tests to also use MMS #12918 [hasezoey](https://github.com/hasezoey) + +6.9.1 / 2023-02-06 +================== + * fix(document): isModified should not be triggered when setting a nested boolean to the same value as previously #12994 [lpizzinidev](https://github.com/lpizzinidev) + * fix(document): save newly set defaults underneath single nested subdocuments #13002 #12905 + * fix(update): handle custom discriminator model name when casting update #12947 [wassil](https://github.com/wassil) + * fix(connection): handles unique autoincrement ID for connections #12990 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): fix type of options of Model.aggregate #12933 [ghost91-](https://github.com/ghost91-) + * fix(types): fix "near" aggregation operator input type #12954 [Jokero](https://github.com/Jokero) + * fix(types): add missing Top operator to AccumulatorOperator type declaration #12952 [lpizzinidev](https://github.com/lpizzinidev) + * docs(transactions): added example for Connection.transaction() method #12943 #12934 [lpizzinidev](https://github.com/lpizzinidev) + * docs(populate): fix out of date comment referencing onModel property #13000 + * docs(transactions): fix typo in transactions.md #12995 [Parth86](https://github.com/Parth86) + +6.9.0 / 2023-01-25 +================== + * feat(schema): add removeVirtual(path) function to schema #12920 [IslandRhythms](https://github.com/IslandRhythms) + * fix(cast): remove empty `$or` conditions after strict applied #12898 [0x0a0d](https://github.com/0x0a0d) + * docs: fixed typo #12946 [Gbengstar](https://github.com/Gbengstar) + +6.8.5 / 2023-01-23 +================== + * fix(query): correctly pass context when casting $elemMatch #12915 #12909 #12902 [MohOraby](https://github.com/MohOraby) + +6.8.4 / 2023-01-17 +================== + * fix(collection): handle creating model when connection disconnected with bufferCommands = false #12889 + * fix(populate): merge instead of overwrite when match is on _id #12891 + * fix: add guard to stop loadClass copying Document if Document is used as base of loaded class (same hack as implemented for Model already) #12820 [sgpinkus](https://github.com/sgpinkus) + * fix(types): correctly infer types on document arrays #12884 #12882 [JavaScriptBach](https://github.com/JavaScriptBach) + * fix(types): added omit for ArraySubdocument type in LeanType declaration #12903 [piyushk96](https://github.com/piyushk96) + * fix(types): add returnDocument type safety #12906 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez) + * docs(typescript): add notes about virtual context to Mongoose 6 migration and TypeScript virtuals docs #12912 #12806 + * docs(schematypes): removed dead link and fixed formatting #12897 #12885 [lpizzinidev](https://github.com/lpizzinidev) + * docs: fix link to lean api #12910 [manniL](https://github.com/manniL) + * docs: list all possible strings for schema.pre in one place #12868 + * docs: add list of known incompatible npm packages #12892 [IslandRhythms](https://github.com/IslandRhythms) + +6.8.3 / 2023-01-06 +================== + * perf: improve performance of assignRawDocsToIdStructure for faster populate on large docs #12867 [Uzlopak](https://github.com/Uzlopak) + * fix(model): ensure consistent ordering of validation errors in insertMany() with ordered: false and rawResult: true #12866 + * fix: avoid passing final callback to pre hook, because calling the callback can mess up hook execution #12836 + * fix(types): avoid inferring timestamps if methods, virtuals, or statics set #12871 + * fix(types): correctly infer string enums on const arrays #12870 [JavaScriptBach](https://github.com/JavaScriptBach) + * fix(types): allow virtuals to be invoked in the definition of other virtuals #12874 [sffc](https://github.com/sffc) + * fix(types): add type def for Aggregate#model without arguments #12864 [hasezoey](https://github.com/hasezoey) + * docs(discriminators): add section about changing discriminator key #12861 + * docs(typescript): explain that virtuals inferred from schema only show up on Model, not raw document type #12860 #12684 + +6.8.2 / 2022-12-28 +================== + * fix(schema): propagate strictQuery to implicitly created schemas for embedded discriminators #12827 #12796 + * fix(model): respect discriminators with Model.validate() #12824 #12621 + * fix(query): fix unexpected validation error when doing findOneAndReplace() with a nullish value #12826 #12821 + * fix(discriminator): apply built-in plugins to discriminator schema even if mergeHooks and mergePlugins are both false #12833 #12696 + * fix(types): add option "overwriteModels" as a schema option #12817 #12816 [hasezoey](https://github.com/hasezoey) + * fix(types): add property "defaultOptions" #12818 [hasezoey](https://github.com/hasezoey) + * docs: make search bar respect documentation version, so you can search 5.x docs #12548 + * docs(typescript): make note about recommending strict mode when using auto typed schemas #12825 #12420 + * docs: add section on sorting to query docs #12588 [IslandRhythms](https://github.com/IslandRhythms) + * test(query.test): add write-concern option #12829 [hasezoey](https://github.com/hasezoey) + +6.8.1 / 2022-12-19 +================== + * fix(query): avoid throwing circular dependency error if same object is used in multiple properties #12774 [orgads](https://github.com/orgads) + * fix(map): return value from super.delete() #12777 [danbrud](https://github.com/danbrud) + * fix(populate): handle virtual populate underneath document array with justOne=true and sort set where 1 element has only 1 result #12815 #12730 + * fix(update): handle embedded discriminators when casting array filters #12802 #12565 + * fix(populate): avoid calling transform if there's no populate results and using lean #12804 #12739 + * fix(model): prevent index creation on syncIndexes if not necessary #12785 #12250 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): correctly infer this when using pre('updateOne') with { document: true, query: false } #12778 + * fix(types): make InferSchemaType: consider { required: boolean } required if it isn't explicitly false #12784 [JavaScriptBach](https://github.com/JavaScriptBach) + * docs: replace many occurrences of "localhost" with "127.0.0.1" #12811 #12741 [hasezoey](https://github.com/hasezoey) [SadiqOnGithub](https://github.com/SadiqOnGithub) + * docs(mongoose): Added missing options to set #12810 [lpizzinidev](https://github.com/lpizzinidev) + * docs: add info on `$locals` parameters to getters/setters tutorial #12814 #12550 [IslandRhythms](https://github.com/IslandRhythms) + * docs: make Document.prototype.$clone() public #12803 + * docs(query): updated explanation for slice #12776 #12474 [lpizzinidev](https://github.com/lpizzinidev) + * docs(middleware): fix broken links #12787 [lpizzinidev](https://github.com/lpizzinidev) + * docs(queries): fixed broken links #12790 [lpizzinidev](https://github.com/lpizzinidev) + +6.8.0 / 2022-12-05 +================== + * feat: add alpha support for Deno #12397 #9056 + * feat: add deprecation warning for default strictQuery #12666 + * feat: upgrade to MongoDB driver 4.12.1 + * feat(schema): add doc as second params to validation message function #12564 #12651 [IslandRhythms](https://github.com/IslandRhythms) + * feat(document): add $clone method #12549 #11849 [lpizzinidev](https://github.com/lpizzinidev) + * feat(populate): allow overriding `localField` and `foreignField` for virtual populate #12657 #6963 [IslandRhythms](https://github.com/IslandRhythms) + * feat(schema+types): add { errorHandler: true } option to Schema post() for better TypeScript support #12723 #12583 + * feat(debug): allow setting debug on a per-connection basis #12704 #12700 [lpizzinidev](https://github.com/lpizzinidev) + * feat: add rewind function to QueryCursor #12710 [passabilities](https://github.com/passabilities) + * feat(types): infer timestamps option from schema #12731 #12069 + * docs: change links to not link to api.html anymore #12644 [hasezoey](https://github.com/hasezoey) + +6.7.5 / 2022-11-30 +================== + * fix(schema): copy indexes when calling add() with schema instance #12737 #12654 + * fix(query): handle deselecting _id when another field has schema-level select: false #12736 #12670 + * fix(types): support using UpdateQuery in bulkWrite() #12742 #12595 + * docs(middleware): added note about execution policy on subdocuments #12735 #12694 [lpizzinidev](https://github.com/lpizzinidev) + * docs(validation): clarify context for update validators in validation docs #12738 #12655 [IslandRhythms](https://github.com/IslandRhythms) + +6.7.4 / 2022-11-28 +================== + * fix: allow setting global strictQuery after Schema creation #12717 #12703 [lpizzinidev](https://github.com/lpizzinidev) + * fix(cursor): make eachAsync() avoid modifying batch when mixing parallel and batchSize #12716 + * fix(types): infer virtuals in query results #12727 #12702 #12684 + * fix(types): correctly infer ReadonlyArray types in schema definitions #12720 + * fix(types): avoid typeof Query with generics for TypeScript 4.6 support #12712 #12688 + * chore: avoid bundling .tgz files when publishing #12725 [hasezoey](https://github.com/hasezoey) + +6.7.3 / 2022-11-22 +================== + * fix(document): handle setting array to itself after saving and pushing a new value #12672 #12656 + * fix(types): update replaceWith pipeline stage #12715 [coyotte508](https://github.com/coyotte508) + * fix(types): remove incorrect modelName type definition #12682 #12669 [lpizzinidev](https://github.com/lpizzinidev) + * fix(schema): fix setupTimestamps for browser.umd #12683 [raphael-papazikas](https://github.com/raphael-papazikas) + * docs: correct justOne description #12686 #12599 [tianguangcn](https://github.com/tianguangcn) + * docs: make links more consistent #12690 #12645 [hasezoey](https://github.com/hasezoey) + * docs(document): explain that $isNew is false in post('save') hooks #12685 #11990 + * docs: fixed line causing a "used before defined" linting error #12707 [sgpinkus](https://github.com/sgpinkus) + +6.7.2 / 2022-11-07 +================== + * fix(discriminator): skip copying base schema plugins if `applyPlugins == false` #12613 #12604 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): add UUID to types #12650 #12593 + * fix(types): allow setting SchemaTypeOptions' index property to IndexOptions #12562 + * fix(types): set this to doc type in SchemaType.prototype.validate() #12663 #12590 + * fix(types): correct handling for model #12659 #12573 + * fix(types): pre hook with deleteOne should resolve this as Query #12642 #12622 [lpizzinidev](https://github.com/lpizzinidev) + +6.7.1 / 2022-11-02 +================== + * fix(query): select Map field with select: false when explicitly requested #12616 #12603 [lpizzinidev](https://github.com/lpizzinidev) + * fix: correctly find paths underneath single nested document with an array of mixed #12605 #12530 + * fix(populate): better support for populating maps of arrays of refs #12601 #12494 + * fix(types): add missing create constructor signature override type #12585 [naorpeled](https://github.com/naorpeled) + * fix(types): make array paths optional in inferred type of array default returns undefined #12649 #12420 + * fix(types): improve ValidateOpts type #12606 [Freezystem](https://github.com/Freezystem) + * docs: add Lodash guide highlighting issues with cloneDeep() #12609 + * docs: removed v5 link from v6 docs #12641 #12624 [lpizzinidev](https://github.com/lpizzinidev) + * docs: removed outdated connection example #12618 [lpizzinidev](https://github.com/lpizzinidev) + +6.7.0 / 2022-10-24 +================== + * feat: upgrade to mongodb driver 4.11.0 #12446 + * feat: add UUID Schema Type (BSON Buffer SubType 4) #12268 #3208 [hasezoey](https://github.com/hasezoey) + * feat(aggregation): add $fill pipeline stage #12545 [raphael-papazikas](https://github.com/raphael-papazikas) + * feat(types+schema): allow defining schema paths using mongoose.Types.* to work around TS type inference issues #12352 + * feat(schema): add alias() method that makes it easier to define multiple aliases for a given path #12368 + * feat(model): add mergeHooks option to Model.discriminator() to avoid duplicate hooks #12542 + * feat(document): add $timestamps() method to set timestamps for save(), bulkSave(), and insertMany() #12540 + +6.6.7 / 2022-10-21 +================== + * fix: correct browser build and improve isAsyncFunction check for browser #12577 #12576 #12392 + * fix(query): allow overwriting discriminator key with overwriteDiscriminatorKey if strict: 'throw' #12578 #12513 + +6.6.6 / 2022-10-20 +================== + * fix(update): handle runValidators when using $set on a doc array in discriminator schema #12571 #12518 + * fix(document): allow creating document with document array and top-level key named schema #12569 #12480 + * fix(cast): make schema-level strictQuery override schema-level strict for query filters #12570 #12508 + * fix(aggregate): avoid adding extra $match stage if user manually set discriminator key to correct value in first pipeline stage #12568 #12478 + * fix: Throws error when updating a key name that match the discriminator key name on nested object #12534 #12517 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): add limit to $filter expression #12553 [raphael-papazikas](https://github.com/raphael-papazikas) + * fix(types): correct replaceWith type pipeline stage #12535 [FabioCingottini](https://github.com/FabioCingottini) + * fix(types): add missing densify type pipeline type #12533 [FabioCingottini](https://github.com/FabioCingottini) + * docs(populate): added transform option description #12560 #12551 [lpizzinidev](https://github.com/lpizzinidev) + * docs(connection): add sample to useDb() documentation #12541 [lpizzinidev](https://github.com/lpizzinidev) + * docs(guide): update broken read-preference links #12538 #12525 [hasezoey](https://github.com/hasezoey) + * chore: add TypeScript version field to issue template #12532 [hasezoey](https://github.com/hasezoey) + +6.6.5 / 2022-10-05 +================== + * fix(document): set defaults on subdocuments underneath init-ed single nested subdocument #12523 #12515 + * fix: make Jest fake timers check more robust to other libs that overwrite time functions #12527 #12514 + * fix(types): indicate that Schema.prototype.discriminator() returns this #12522 #12457 + * fix(types): add "estimatedDocumentCount" and "countDocuments" as possible hooks #12519 #12516 + * docs(models): add section on MongoDB Views #12526 #5694 + * docs(subdocs): clarify that populated docs are not subdocs #12521 #12398 + * docs(change-streams): remove unnecessary obsolete comment about needing to use mongodb driver change streams #12444 + +6.6.4 / 2022-10-03 +================== + * fix(model): avoid saving applied defaults if path is deselected #12506 #12414 + * fix(types): correct DocType for auto typed query helpers #12342 + * fix(types): avoid "excessively deep" type instantiation error when using bulkWrite() with type that extends from document #12277 + * fix(types): avoid relying on typeof this, which isn't supported in TypeScript < 4.4 #12375 + * docs(schema): correct example for Schema.prototype.discriminator() #12493 + * docs(typescript): clean up query helpers examples #12342 + * chore: use mongodb-memory-server for testing #12262 [hasezoey](https://github.com/hasezoey) + +6.6.3 / 2022-09-30 +================== + * fix(query): treat findOne(_id) as equivalent to findOne({ _id }) #12485 #12325 + * fix(timestamps): findOneAndUpdate creates subdocs with timestamps in reverse order #12484 #12475 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): make schema.plugin() more flexible for schemas that don't define any generics #12486 #12454 + * fix(types): add "array of array key-value pairs" as a argument option for "query.sort()" #12483 #12434 [hasezoey](https://github.com/hasezoey) + * fix(types): remove unused defaults in "PluginFunction" #12459 [hasezoey](https://github.com/hasezoey) + * fix(types): update DiscriminatorSchema to have better names and combine statics #12460 [hasezoey](https://github.com/hasezoey) + +6.6.2 / 2022-09-26 +================== + * fix(model): avoid deleting shared schema methods in fix for #12254 #12423 + * fix(document): set $inc default value in case field has not been specified on the document #12435 [lpizzinidev](https://github.com/lpizzinidev) + * fix(query): handle `select: false` on map paths in query results #12467 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): add HydratedDocumentFromSchema to make it easier to pull inferred hydrated doc type #12464 #12319 + * fix(types): add sanitizeFilter to types #12465 [zrosenbauer](https://github.com/zrosenbauer) + * fix(types): infer number enum types from schema if using enum: [0, 1] as const #12463 #12242 + * docs(validation): add section on global schematype validation, clean up other issues #12430 + * docs: add clarification about overwrite flag in model.js #12447 [Tzvika-m](https://github.com/Tzvika-m) + * docs: change to consistent "Example:" for jsdoc comments #12432 [hasezoey](https://github.com/hasezoey) + +6.6.1 / 2022-09-14 +================== + * fix: correctly apply defaults after subdoc init #12328 + * fix(array): avoid using default _id when using pull() #12294 + * fix: allow null values inside $expr objects #12429 [MartinDrost](https://github.com/MartinDrost) + * fix(query): use correct Query constructor when cloning query #12418 + * docs(website): remove setting "latest38x" which is not used anywhere #12396 [hasezoey](https://github.com/hasezoey) + +6.6.0 / 2022-09-08 +================== + * feat: upgrade mongodb driver -> 4.9.1 #12370 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez) + * feat: re-export default Mongoose instance properties for ESM named imports support #12256 + * feat(model): add option to skip invalid fields with castObject() #12156 [IslandRhythms](https://github.com/IslandRhythms) + * feat: use setPrototypeOf() instead of __proto__ to allow running on Deno #12315 + * feat(QueryCursor): add support for AbortSignal on eachAsync() #12323 + * feat(types): add types for new $densify operator #12118 [IslandRhythms](https://github.com/IslandRhythms) + +6.5.5 / 2022-09-07 +================== + * fix(setDefaultsOnInsert): avoid applying defaults on insert if nested property set #12279 + * fix(model): make applyHooks() and applyMethods() handle case where custom method is set to Mongoose implementation #12254 + * fix(types): add string "ascending" and "descending" index-directions #10269 + * docs: upgrade dox to 1.0.0 #12403 [hasezoey](https://github.com/hasezoey) + * docs: update old mongodb nodejs driver documentation urls #12387 [hasezoey](https://github.com/hasezoey) + * docs: update JSDOC ... (spread) definition #12388 [hasezoey](https://github.com/hasezoey) + * refactor(model): allow optionally passing indexes to createIndexes and cleanIndexes #12280 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez) + +6.5.4 / 2022-08-30 +================== + * fix(document): allow calling $assertPopulated() with values to better support manual population #12233 + * fix(connection+mongoose): better handling for calling model() with 1 argument #12359 + * fix(model): allow defining discriminator virtuals and methods using schema options #12326 + * fix(types): fix MongooseQueryMiddleware missing "findOneAndReplace" and "replaceOne" #12330 #12329 [Jule-](https://github.com/Jule-) [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): fix replaceOne return type #12351 [lpizzinidev](https://github.com/lpizzinidev) + * fix(types): use this for return type from $assertPopulated() #12234 + * docs: highlight how to connect using auth in README #12354 [AntonyOnScript](https://github.com/AntonyOnScript) + * docs: improve jsdoc comments for private methods #12337 [hasezoey](https://github.com/hasezoey) + * docs: fix minor typo in compatibility table header #12355 [skyme5](https://github.com/skyme5) + 6.5.3 / 2022-08-24 ================== * fix(document): handle maps when applying defaults to nested paths #12322 @@ -358,7 +668,7 @@ * fix(index.d.ts): ValidationError `errors` only contains CastError or ValidationError #11369 [Uzlopak](https://github.com/Uzlopak) * fix(index.d.ts): make InsertManyResult.insertedIds return an array of Types.ObjectId by default #11197 * fix(index.d.ts): allow pre('save') middleware with pre options #11257 - * fix(index.d.ts): add `supressReservedKeysWarning` option to schema #11439 [hiukky](https://github.com/hiukky) + * fix(index.d.ts): add `suppressReservedKeysWarning` option to schema #11439 [hiukky](https://github.com/hiukky) * docs(connections): improve replica set hostname docs with correct error message and info about `err.reason.servers` #11200 * docs(populate): add virtual populate match option documentation #11411 [remirobichet](https://github.com/remirobichet) * docs(document): add note to API docs that flattenMaps defaults to `true` for `toJSON()` but not `toObject()` #11213 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 895ca4587ae..4b5246b66ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,7 @@ If you have a question about Mongoose (not a bug report) please post it to eithe - Write typings-tests if you modify the typescript-typings. (tests are in the [test/types](https://github.com/Automattic/mongoose/tree/master/test/types) directory). ### Running the tests + - Open a terminal and navigate to the root of the project - execute `npm install` to install the necessary dependencies - execute `npm run mongo` to start a MongoDB instance on port 27017. This step is optional, if you have already a database running on port 27017. To spin up a specific mongo version, you can do it by executing `npm run mongo -- {version}`. E.g. you want to spin up a mongo 4.2.2 server, you execute `npm run mongo -- 4.2.2` @@ -48,40 +49,41 @@ If you have a question about Mongoose (not a bug report) please post it to eithe ### Documentation -To contribute to the [API documentation](http://mongoosejs.com/docs/api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/Automattic/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. +To contribute to the [API documentation](http://mongoosejs.com/docs/api/mongoose.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/Automattic/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. -To contribute to the [guide](http://mongoosejs.com/docs/guide.html) or [quick start](http://mongoosejs.com/docs/index.html) docs, make your changes to the appropriate `.pug` files in the [docs](https://github.com/Automattic/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. +To contribute to the [guide](http://mongoosejs.com/docs/guide.html) or [quick start](http://mongoosejs.com/docs/index.html) docs, make your changes to the appropriate `.pug` / `.md` files in the [docs](https://github.com/Automattic/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute: * `npm install` * `npm run docs:view` -Visit `http://localhost:8089` and you should see the docs with your local changes. Make sure you `npm run docs:clean` before committing, because automated generated files to `docs/*` should **not** be in PRs. +Visit `http://127.0.0.1:8089` and you should see the docs with your local changes. Make sure you `npm run docs:clean` before committing, because automated generated files to `docs/*` should **not** be in PRs. + +#### Documentation Style Guidelines + +There are some guidelines to keep the style for the documentation consistent: + +- All links that refer to some other file in the mongoose documentation needs to be relative without a prefix unless required (use `guide.html` over `./guide.html` or `/docs/guide.html`) ### Plugins website The [plugins](http://plugins.mongoosejs.io/) site is also an [open source project](https://github.com/vkarpov15/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! - ## Financial contributions We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/mongoose). Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed. - ## Credits - ### Contributors Thank you to all the people who have already contributed to mongoose! - ### Backers Thank you to all our backers! [[Become a backer](https://opencollective.com/mongoose#backer)] - diff --git a/README.md b/README.md index 60da3ccde9f..adc760dc2e5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # Mongoose -Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks. +Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. Mongoose supports [Node.js](https://nodejs.org/en/) and [Deno](https://deno.land/) (alpha). -[![Slack Status](https://img.shields.io/badge/slack-mongoosejsteam-34D058.svg?logo=slack )](https://mongoosejsteam.slack.com) [![Build Status](https://github.com/Automattic/mongoose/workflows/Test/badge.svg)](https://github.com/Automattic/mongoose) [![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) +[![Deno version](https://deno.land/badge/mongoose/version)](https://deno.land/x/mongoose) +[![Deno popularity](https://deno.land/badge/mongoose/popularity)](https://deno.land/x/mongoose) [![npm](https://nodei.co/npm/mongoose.png)](https://www.npmjs.com/package/mongoose) @@ -20,7 +21,7 @@ Mongoose 6.0.0 was released on August 24, 2021. You can find more details on [ba - [Bug Reports](https://github.com/Automattic/mongoose/issues/) - [Mongoose Slack Channel](http://slack.mongoosejs.io/) - [Help Forum](http://groups.google.com/group/mongoose-orm) - - [MongoDB Support](https://docs.mongodb.org/manual/support/) + - [MongoDB Support](https://www.mongodb.com/docs/manual/support/) ## Plugins @@ -45,6 +46,8 @@ First install [Node.js](http://nodejs.org/) and [MongoDB](https://www.mongodb.or $ npm install mongoose ``` +Mongoose 6.8.0 also includes alpha support for [Deno](https://deno.land/). + ## Importing ```javascript @@ -55,6 +58,24 @@ const mongoose = require('mongoose'); import mongoose from 'mongoose'; ``` +Or, using [Deno's `createRequire()` for CommonJS support](https://deno.land/std@0.113.0/node/README.md?source=#commonjs-modules-loading) as follows. + +```javascript +import { createRequire } from "https://deno.land/std/node/module.ts"; +const require = createRequire(import.meta.url); + +const mongoose = require('mongoose'); + +mongoose.connect('mongodb://127.0.0.1:27017/test') + .then(() => console.log('Connected!')); +``` + +You can then run the above script using the following. + +``` +deno run --allow-net --allow-read --allow-sys --allow-env mongoose-test.js +``` + ## Mongoose for Enterprise Available as part of the Tidelift Subscription @@ -70,7 +91,7 @@ First, we need to define a connection. If your app uses only one database, you s Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters `host, database, port, options`. ```js -await mongoose.connect('mongodb://localhost/my_database'); +await mongoose.connect('mongodb://127.0.0.1/my_database'); ``` Once connected, the `open` event is fired on the `Connection` instance. If you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. Otherwise, `mongoose.createConnection` return value is a `Connection`. @@ -98,9 +119,9 @@ const BlogPost = new Schema({ Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of: * [Validators](http://mongoosejs.com/docs/validation.html) (async and sync) -* [Defaults](http://mongoosejs.com/docs/api.html#schematype_SchemaType-default) -* [Getters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-get) -* [Setters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set) +* [Defaults](http://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-default) +* [Getters](http://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-get) +* [Setters](http://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-set) * [Indexes](http://mongoosejs.com/docs/guide.html#indexes) * [Middleware](http://mongoosejs.com/docs/middleware.html) * [Methods](http://mongoosejs.com/docs/guide.html#methods) definition @@ -316,7 +337,7 @@ return a cursor. ## API Docs -Find the API docs [here](http://mongoosejs.com/docs/api.html), generated using [dox](https://github.com/tj/dox) +Find the API docs [here](http://mongoosejs.com/docs/api/mongoose.html), generated using [dox](https://github.com/tj/dox) and [acquit](https://github.com/vkarpov15/acquit). ## Related Projects diff --git a/benchmarks/benchjs/delete.js b/benchmarks/benchjs/delete.js index 705c8091fe1..1d717f7f6e3 100644 --- a/benchmarks/benchjs/delete.js +++ b/benchmarks/benchjs/delete.js @@ -17,11 +17,11 @@ const mongoClient = require('mongodb').MongoClient; * These are all the benchmark tests for deleting data */ -mongoose.connect('mongodb://localhost/mongoose-bench', function (err) { +mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { if (err) { throw err; } - mongoClient.connect('mongodb://localhost', function (err, client) { + mongoClient.connect('mongodb://127.0.0.1', function (err, client) { if (err) { throw err; } diff --git a/benchmarks/benchjs/insert.js b/benchmarks/benchjs/insert.js index 7b13f90dcde..cd01bfb6069 100644 --- a/benchmarks/benchjs/insert.js +++ b/benchmarks/benchjs/insert.js @@ -19,12 +19,12 @@ const ObjectId = Schema.Types.ObjectId; * These are all the benchmark tests for inserting data */ -mongoose.connect('mongodb://localhost/mongoose-bench', function (err) { +mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { if (err) { throw err; } mongoClient.connect( - 'mongodb://localhost/mongoose-bench', + 'mongodb://127.0.0.1/mongoose-bench', function (err, client) { if (err) { throw err; diff --git a/benchmarks/benchjs/multiop.js b/benchmarks/benchjs/multiop.js index bfe540705fd..c3f73d1f730 100644 --- a/benchmarks/benchjs/multiop.js +++ b/benchmarks/benchjs/multiop.js @@ -19,11 +19,11 @@ const utils = require('../../lib/utils.js'); * These are all the benchmark tests for mixed data operations */ -mongoose.connect('mongodb://localhost/mongoose-bench', function (err) { +mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { if (err) { throw err; } - mongoClient.connect('mongodb://localhost', function (err, client) { + mongoClient.connect('mongodb://127.0.0.1', function (err, client) { if (err) { throw err; } diff --git a/benchmarks/benchjs/population.js b/benchmarks/benchjs/population.js index 81b46ed2799..dc55ac1cae9 100644 --- a/benchmarks/benchjs/population.js +++ b/benchmarks/benchjs/population.js @@ -18,7 +18,7 @@ const utils = require('../../lib/utils.js'); * These are all the benchmark tests for population ops */ -mongoose.connect('mongodb://localhost/mongoose-bench', function (err) { +mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { if (err) { throw err; } diff --git a/benchmarks/benchjs/read.js b/benchmarks/benchjs/read.js index e97e2fab842..35d39b90916 100644 --- a/benchmarks/benchjs/read.js +++ b/benchmarks/benchjs/read.js @@ -20,11 +20,11 @@ const utils = require('../../lib/utils.js'); * These are all the benchmark tests for reading data */ -mongoose.connect('mongodb://localhost/mongoose-bench', function (err) { +mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { if (err) { throw err; } - mongoClient.connect('mongodb://localhost', function (err, client) { + mongoClient.connect('mongodb://127.0.0.1', function (err, client) { if (err) { throw err; } diff --git a/benchmarks/benchjs/update.js b/benchmarks/benchjs/update.js deleted file mode 100644 index cb745742a55..00000000000 --- a/benchmarks/benchjs/update.js +++ /dev/null @@ -1,401 +0,0 @@ -'use strict'; - -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const mongoClient = require('mongodb').MongoClient; -const ObjectId = Schema.Types.ObjectId; -const utils = require('../../lib/utils.js'); - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for updating data - */ - -mongoose.connect('mongodb://localhost/mongoose-bench', function (err) { - if (err) { - throw err; - } - mongoClient.connect('mongodb://localhost', function (err, client) { - if (err) { - throw err; - } - - const db = client.db('mongoose-bench'); - - const Comments = new Schema(); - Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments], - }); - - let BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number, - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - owners: [ObjectId], - comments: [Comments], - def: { type: String, default: 'kandinsky' }, - }); - - const blogData = { - title: 'dummy post', - author: 'somebody', - slug: 'test.post', - date: new Date(), - meta: { date: new Date(), visitors: 9001 }, - published: true, - mixed: { thisIsRandom: true }, - numbers: [1, 2, 7, 10, 23432], - tags: ['test', 'BENCH', 'things', 'more things'], - def: 'THANGS!!!', - comments: [], - }; - - const commentData = { - title: 'test comment', - date: new Date(), - body: 'this be some crazzzyyyyy text that would go in a comment', - comments: [{ title: 'second level', date: new Date(), body: 'texttt' }], - }; - - for (let i = 0; i < 5; i++) { - blogData.comments.push(commentData); - } - - const UserSchema = new Schema({ - name: String, - age: Number, - likes: [String], - address: String, - }); - - const User = mongoose.model('User', UserSchema); - BlogPost = mongoose.model('BlogPost', BlogPost); - const user = db.collection('user'); - const blogpost = db.collection('blogpost'); - - const mIds = []; - const dIds = []; - - const bmIds = []; - const bdIds = []; - - const data = { - name: 'name', - age: 0, - likes: ['dogs', 'cats', 'pizza'], - address: ' Nowhere-ville USA', - }; - - // this is for some of the update tests below - let testBp; - // insert all of the data here - let count = 4000; - for (let i = 0; i < 1000; i++) { - User.create(data, function (err, u) { - if (err) { - throw err; - } - mIds.push(u.id); - --count || next(); - }); - const nData = utils.clone(data); - user.insertOne(nData, function (err, res) { - dIds.push(res.insertedId); - --count || next(); - }); - BlogPost.create(blogData, function (err, bp) { - if (err) { - throw err; - } - bmIds.push(bp.id); - testBp = bp; - --count || next(); - }); - - const bpData = utils.clone(blogData); - blogpost.insertOne(bpData, function (err, res) { - if (err) { - throw err; - } - bdIds.push(res.insertedId); - --count || next(); - }); - } - - let mi = 0, - di = 0, - bmi = 0, - bdi = 0; - - function getNextmId() { - mi = ++mi % mIds.length; - return mIds[mi]; - } - - function getNextdId() { - di = ++di % dIds.length; - return dIds[di]; - } - - function getNextbmId() { - bmi = ++bmi % bmIds.length; - return bmIds[bmi]; - } - - function getNextbdId() { - bdi = ++bdi % bdIds.length; - return bdIds[bdi]; - } - - function closeDB() { - mongoose.connection.db.dropDatabase(function () { - mongoose.disconnect(); - process.exit(); - }); - } - - suite - .add('Update - Mongoose - Basic', { - defer: true, - fn: function (deferred) { - User.update( - { _id: getNextmId() }, - { $set: { age: 2 }, $push: { likes: 'metal' } }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Update - Driver - Basic', { - defer: true, - fn: function (deferred) { - user.updateOne( - { _id: getNextdId() }, - { $set: { age: 2 }, $push: { likes: 'metal' } }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Update - Mongoose - Embedded Docs', { - defer: true, - fn: function (deferred) { - BlogPost.findOne({ _id: getNextbmId() }, function (err, bp) { - if (err) { - throw err; - } - bp.comments[3].title = 'this is a new title'; - bp.comments[0].date = new Date(); - bp.comments.push(commentData); - // save in Mongoose behaves differently than it does in the driver. - // The driver will send the full document, while mongoose will check - // and only update fields that have been changed. This is meant to - // illustrate that difference between the two - bp.save(function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }); - }, - }) - .add('Update - Driver - Embdedded Docs', { - defer: true, - fn: function (deferred) { - blogpost.findOne({ _id: getNextbdId() }, function (err, bp) { - if (err) { - throw err; - } - blogpost.updateOne( - { _id: bp._id }, - { - $set: { - 'comments.3.title': 'this is a new title', - 'comments.0.date': new Date(), - }, - }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }); - }, - }) - .add('Update - Mongoose - Multiple Documents', { - defer: true, - fn: function (deferred) { - const ids = []; - for (let i = 0; i < 50; i++) { - ids.push(getNextmId()); - } - User.update( - { _id: { $in: ids } }, - { $set: { age: 2 }, $push: { likes: 'metal' } }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Update - Driver - Multiple Documents', { - defer: true, - fn: function (deferred) { - const ids = []; - for (let i = 0; i < 50; i++) { - ids.push(getNextdId()); - } - user.updateOne( - { _id: { $in: ids } }, - { $set: { age: 2 }, $push: { likes: 'metal' } }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Update - Mongoose - pop and push', { - defer: true, - fn: function (deferred) { - testBp.comments.push(commentData); - testBp.comments.$shift(); - testBp.save(function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Update - Mongoose - Array Manipulation, parallel ops', { - defer: true, - fn: function (deferred) { - let done = false; - BlogPost.update( - { _id: testBp.id }, - { $pop: { comments: -1 } }, - function (err) { - if (err) { - throw err; - } - done && deferred.resolve(); - done = true; - } - ); - BlogPost.update( - { _id: testBp.id }, - { $push: { comments: commentData } }, - function (err) { - if (err) { - throw err; - } - done && deferred.resolve(); - done = true; - } - ); - }, - }) - .add('Update - Mongoose - findOneAndModify', { - defer: true, - fn: function (deferred) { - BlogPost.findOneAndUpdate( - { _id: getNextbmId() }, - { $set: { age: 2 }, $push: { likes: 'metal' } }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Update - Mongoose - find and update, separate ops', { - defer: true, - fn: function (deferred) { - BlogPost.findOne({ _id: getNextbmId() }, function (err, bp) { - if (err) { - throw err; - } - bp.update( - { $set: { age: 2 }, $push: { likes: 'metal' } }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }); - }, - }) - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - closeDB(); - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }); - function next() { - for (let i = 0; i < 100; i++) { - testBp.comments.push(commentData); - } - testBp.save(function (err) { - if (err) { - throw err; - } - suite.run({ async: true }); - }); - } - }); -}); diff --git a/benchmarks/mem.js b/benchmarks/mem.js index 1864562056d..c73acac33e4 100644 --- a/benchmarks/mem.js +++ b/benchmarks/mem.js @@ -4,7 +4,7 @@ const mongoose = require('../'); const Schema = mongoose.Schema; -mongoose.connect('mongodb://localhost/mongoose-bench'); +mongoose.connect('mongodb://127.0.0.1/mongoose-bench'); const DocSchema = new Schema({ title: String diff --git a/benchmarks/populate.js b/benchmarks/populate.js index a5f7476b04f..2be29e72e0e 100644 --- a/benchmarks/populate.js +++ b/benchmarks/populate.js @@ -18,7 +18,7 @@ const B = mongoose.model('B', Schema({ let start; let count = 0; -mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { +mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function(err) { if (err) { return done(err); } diff --git a/benchmarks/typescript.js b/benchmarks/typescript.js deleted file mode 100644 index bff7d1d9682..00000000000 --- a/benchmarks/typescript.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; - -const { exec } = require('child_process'); -const fs = require('node:fs/promises'); -const mongoose = require('../'); - -const numIterations = 10; -run().catch(err => { - console.error(err); - mongoose.disconnect(); - process.exit(-1); -}); - -async function run() { - if (process.env.DB_URL) { - await mongoose.connect(process.env.DB_URL); - } - - - const results = []; - - const tsProjectsDirectories = await fs.readdir('benchmarks/typescript'); - - let failed = []; - - for (const tsProjectDirectory of tsProjectsDirectories) { - let instantiations = 0; - let memoryUsed = 0; - let checkTime = 0; - let totalTime = 0; - - for (let i = 0; i < numIterations; ++i) { - const { stdout } = await execPromise( - '../../../node_modules/.bin/tsc --extendedDiagnostics', - { cwd: `${__dirname}/typescript/${tsProjectDirectory}` } - ); - - const lines = stdout.split('\n'); - - const _instantiations = +lines.find(line => line.startsWith('Instantiations:')).match(/\d+/)[0]; - const _memoryUsed = +lines.find(line => line.startsWith('Memory used:')).match(/\d+/)[0]; - const _checkTime = +lines.find(line => line.startsWith('Check time:')).match(/\d+(\.\d+)?/)[0]; - const _totalTime = +lines.find(line => line.startsWith('Total time:')).match(/\d+(\.\d+)?/)[0]; - - instantiations += _instantiations; - memoryUsed += _memoryUsed; - checkTime += _checkTime; - totalTime += _totalTime; - } - - instantiations /= numIterations; - memoryUsed /= numIterations; - checkTime /= numIterations; - totalTime /= numIterations; - - console.log(`${tsProjectDirectory} instantiations:`, instantiations); - console.log(`${tsProjectDirectory} memory used:`, memoryUsed); - console.log(`${tsProjectDirectory} check time:`, checkTime); - console.log(`${tsProjectDirectory} total time:`, totalTime); - results.push({ - instantiations, - memoryUsed, - checkTime, - totalTime, - testName: tsProjectDirectory - }); - - if (instantiations >= 100000) { - failed.push(tsProjectDirectory); - } - } - - await persist({ results }); - - await mongoose.disconnect(); - - if (failed.length > 0) { - throw new Error(`Benchmarks ${failed.join(', ')} had over 100k instantiations`); - } -} - -async function persist({ results }) { - if (!process.env.DB_URL) { - return; - } - if (!process.env.GITHUB_SHA) { - return; - } - - const BenchmarkResult = await getBenchmarkResult(); - await BenchmarkResult.updateOne( - { githash: process.env.GITHUB_SHA, benchmarkName: 'TypeScript' }, - { results }, - { upsert: true } - ); -} - -async function getBenchmarkResult() { - if (mongoose.models.BenchmarkResult) { - return mongoose.models.BenchmarkResult; - } - - const benchmarkResultsSchema = mongoose.Schema({ - githash: { type: String, required: true }, - benchmarkName: { type: String, required: true }, - results: 'Mixed' - }, { timestamps: true }); - - benchmarkResultsSchema.index({ githash: 1, benchmarkName: 1 }, { unique: true }); - - - const BenchmarkResult = mongoose.model('BenchmarkResult', benchmarkResultsSchema, 'BenchmarkResult'); - - await BenchmarkResult.syncIndexes(); - return BenchmarkResult; -} - -function execPromise(command, options) { - return new Promise(function(resolve, reject) { - exec(command, options, (error, stdout, stderr) => { - if (error) { - console.error(error); - console.error(stdout); - console.error(stderr); - reject(error); - return; - } - - resolve({ stdout }); - }); - }); -} diff --git a/benchmarks/typescript/simple/.npmrc b/benchmarks/typescript/simple/.npmrc new file mode 100644 index 00000000000..43c97e719a5 --- /dev/null +++ b/benchmarks/typescript/simple/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/benchmarks/typescript/simple/index.ts b/benchmarks/typescript/simple/index.ts index 94598304ab3..79fee994ad0 100644 --- a/benchmarks/typescript/simple/index.ts +++ b/benchmarks/typescript/simple/index.ts @@ -16,4 +16,4 @@ const schema = new Schema({ avatar: String }); -const UserModel = model('User', schema); \ No newline at end of file +const UserModel = model('User', schema); diff --git a/benchmarks/typescript/simple/package.json b/benchmarks/typescript/simple/package.json new file mode 100644 index 00000000000..ee74cdf4d70 --- /dev/null +++ b/benchmarks/typescript/simple/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "mongoose": "file:../../../mongoose.tgz", + "typescript": "4.9.x" + }, + "scripts": { + "benchmark": "tsc --extendedDiagnostics" + } +} diff --git a/benchmarks/typescript/simple/tsconfig.json b/benchmarks/typescript/simple/tsconfig.json index 2d269d5449c..fd9e37a6650 100644 --- a/benchmarks/typescript/simple/tsconfig.json +++ b/benchmarks/typescript/simple/tsconfig.json @@ -1,16 +1,5 @@ { - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "baseUrl": ".", - "paths": { - "mongoose": ["../../../"] - } - }, - "esModuleInterop": true, - "outDir": "typescript", - "strictNullChecks": true, "include": [ - "./*.ts", - "../../../index.d.ts" + "./*.ts" ] } \ No newline at end of file diff --git a/docs/api.pug b/docs/api.pug index 92a85648e69..1d5617a29f7 100644 --- a/docs/api.pug +++ b/docs/api.pug @@ -2,66 +2,8 @@ extends layout append style link(rel="stylesheet", href="/docs/css/api.css") - script(src="/docs/js/api-bold-current-nav.js") + script(src="/docs/js/redirect-old-api.js") block content - h1 API Docs - - include includes/native - - div.api-nav - div.api-nav-content - each item in docs - - if (!item.hideFromNav) - div.nav-item(id='nav-' + item.name) - div.nav-item-title - a(href='./api/' + item.name.toLowerCase() + '.html') - | #{item.name} - ul.nav-item-sub - each prop in item.props - li - a(href='./api/' + item.name.toLowerCase() + '.html#' + prop.anchorId) - | #{prop.string} - - each item in docs - hr.separate-api - div.item-header-wrap - - - - h2(id=item.name, class="item-header") - a(href='#' + item.name) - | #{item.name} - ul - each prop in item.props - li - a(href='#' + prop.anchorId) - | #{prop.string} - each prop in item.props - hr.separate-api-elements - h3(id=prop.anchorId) - a(href='#' + prop.anchorId) - | #{prop.string} - if prop.param != null - h5 Parameters - ul.params - each param in prop.param - - if (param.nested) - ul(style="margin-top: 0.5em") - li - | #{param.name} - | «#{param.types}» !{param.description} - - else - li.param - | #{param.name} - | «#{param.types}» !{param.description} - if prop.return != null - h5 Returns: - ul - li «#{prop.return.types}» !{prop.return.description} - if prop.type != null && prop.type !== 'method' && prop.type !== 'function' - h5 Type: - ul - li «#{prop.type}» - div - | !{prop.description} + p Redirecting to proper API page, please wait + noscript This Page requires JavaScript to Redirect old links properly diff --git a/docs/api_split.pug b/docs/api_split.pug index 44b2e573b5d..5118a76032c 100644 --- a/docs/api_split.pug +++ b/docs/api_split.pug @@ -68,7 +68,7 @@ block content if prop.inherits != null h5 Inherits: ul - li «#{prop.inherits}» + li «#{prop.inherits.text}» if prop.see != null && prop.see.length > 0 h5 See: ul diff --git a/docs/async-await.md b/docs/async-await.md index a142567c758..de526b0761d 100644 --- a/docs/async-await.md +++ b/docs/async-await.md @@ -62,7 +62,7 @@ async function awaitUpdate() { } ``` -Note that the specific fulfillment values of different Mongoose methods vary, and may be affected by configuration. Please refer to the [API documentation](./api.html) for information about specific methods. +Note that the specific fulfillment values of different Mongoose methods vary, and may be affected by configuration. Please refer to the [API documentation](api/mongoose.html.html) for information about specific methods. ### Async Functions @@ -108,7 +108,7 @@ Under the hood, [async/await is syntactic sugar](https://developer.mozilla.org/e Due to the surprisingly simple way promises are implemented in JavaScript, the keyword `await` will try to unwrap any object with a property whose key is the string ‘then’ and whose value is a function. Such objects belong to a broader class of objects called [thenables](https://masteringjs.io/tutorials/fundamentals/thenable). If the thenable being unwrapped is a genuine promise, e.g. an instance of the [Promise constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), we enjoy several guarantees about how the object’s ‘then’ function will behave. -However, Mongoose provides several static helper methods that return a different class of thenable object called a [Query](./queries.html)--and [Queries are not promises](./queries.html#queries-are-not-promises). +However, Mongoose provides several static helper methods that return a different class of thenable object called a [Query](queries.html)--and [Queries are not promises](queries.html#queries-are-not-promises). Because Queries are also *thenables*, we can interact with a Query using async/await just as we would interact with a genuine promise, with one key difference: observing the fulfillment value of a genuine promise cannot under any circumstances change that value, but trying to re-observe the value of a Query may cause the Query to be re-executed. ```javascript @@ -147,5 +147,5 @@ async function observeQuery() { ``` You are most likely to accidentally re-execute queries in this way when mixing callbacks with async/await. - This is never necessary and should be avoided. - If you need a Query to return a fully-fledged promise instead of a thenable, you can use [Query#exec()](./api/query.html#query_Query-exec). \ No newline at end of file +This is never necessary and should be avoided. +If you need a Query to return a fully-fledged promise instead of a [thenable](https://masteringjs.io/tutorials/fundamentals/thenable), you can use [Query#exec()](api/query.html#query_Query-exec). diff --git a/docs/change-streams.md b/docs/change-streams.md index dc7eaeb9515..29f0b8a8209 100644 --- a/docs/change-streams.md +++ b/docs/change-streams.md @@ -1,7 +1,7 @@ ## Change Streams -[Change streams](https://www.mongodb.com/developer/quickstart/nodejs-change-streams-triggers/) let you listen for updates to documents in a given model's collection, or even documents in an entire database. -Unlike [middleware](/docs/middleware.html), change streams are a MongoDB server construct, which means they pick up changes from anywhere. +[Change streams](https://www.mongodb.com/developer/languages/javascript/nodejs-change-streams-triggers/) let you listen for updates to documents in a given model's collection, or even documents in an entire database. +Unlike [middleware](middleware.html), change streams are a MongoDB server construct, which means they pick up changes from anywhere. Even if you update a document from a MongoDB GUI, your Mongoose change stream will be notified. The `watch()` function creates a change stream. @@ -50,7 +50,7 @@ For local development, we recommend [mongodb-memory-server](https://www.npmjs.co ### Iterating using `next()` -If you want to iterate through a change stream in a [AWS Lambda function](/docs/lambda.html), do **not** use event emitters to listen to the change stream. +If you want to iterate through a change stream in a [AWS Lambda function](lambda.html), do **not** use event emitters to listen to the change stream. You need to make sure you close your change stream when your Lambda function is done executing, because your change stream may end up in an inconsistent state if Lambda stops your container while the change stream is pulling data from MongoDB. Change streams also have a `next()` function that lets you explicitly wait for the next change to come in. @@ -65,9 +65,7 @@ exports.handler = async (event, context) => { context.callbackWaitsForEmptyEventLoop = false; await connectToDatabase(); - - // Use MongoDB Node driver's `watch()` function, because Mongoose change streams - // don't support `next()` yet. See https://github.com/Automattic/mongoose/issues/11527 + const changeStream = await Country.watch([], { resumeAfter }); // Change stream `next()` will wait forever if there are no changes. So make sure to @@ -83,4 +81,4 @@ exports.handler = async (event, context) => { resumeAfter = changeStream.resumeToken; await changeStream.close(); }; -``` \ No newline at end of file +``` diff --git a/docs/compatibility.md b/docs/compatibility.md index f477f185d6b..01f6ebb3926 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -12,22 +12,22 @@ Mongoose relies on the [MongoDB Node.js Driver](http://mongodb.github.io/node-mongodb-native/) to talk to MongoDB. -You can refer to [this table](https://docs.mongodb.com/drivers/node/current/compatibility/) for up-to-date information as to which version of the MongoDB driver supports which version of MongoDB. +You can refer to [this table](https://www.mongodb.com/docs/drivers/node/current/compatibility/) for up-to-date information as to which version of the MongoDB driver supports which version of MongoDB. Below are the [semver](http://semver.org/) ranges representing which versions of mongoose are compatible with the listed versions of MongoDB server. -| MongoDB Sever | Mongoose | -| :-----------: | :----------------------------: | -| `6.x` | `^6.5.0` | -| `5.x` | `^6.0.0` | -| `4.4.x` | `^5.10.0 \| ^6.0.0` | -| `4.2.x` | `^5.7.0 \| ^6.0.0` | -| `4.0.x` | `^5.2.0 \| ^6.0.0` | -| `3.6.x` | `^5.0.0` | -| `3.4.x` | `^4.7.3 \| ^5.0.0` | -| `3.2.x` | `^4.3.0 \| 5.0.0` | -| `3.0.x` | `^3.8.22 \| ^4.0.0 \| ^5.0.0` | -| `2.6.x` | `^3.8.8 \| ^4.0.0` | -| `2.4.x` | `^3.8.0 \| ^4.0.0` | +| MongoDB Server | Mongoose | +| :------------: | :---------------------------: | +| `6.x` | `^6.5.0` | +| `5.x` | `^6.0.0` | +| `4.4.x` | `^5.10.0 \| ^6.0.0` | +| `4.2.x` | `^5.7.0 \| ^6.0.0` | +| `4.0.x` | `^5.2.0 \| ^6.0.0` | +| `3.6.x` | `^5.0.0` | +| `3.4.x` | `^4.7.3 \| ^5.0.0` | +| `3.2.x` | `^4.3.0 \| 5.0.0` | +| `3.0.x` | `^3.8.22 \| ^4.0.0 \| ^5.0.0` | +| `2.6.x` | `^3.8.8 \| ^4.0.0` | +| `2.4.x` | `^3.8.0 \| ^4.0.0` | Note that Mongoose `5.x` dropped support for all versions of MongoDB before `3.0.0`. If you need to use MongoDB `2.6` or older, use Mongoose `4.x`. diff --git a/docs/connections.md b/docs/connections.md index 1a7935adb1a..6c93e13c215 100644 --- a/docs/connections.md +++ b/docs/connections.md @@ -3,7 +3,7 @@ You can connect to MongoDB with the `mongoose.connect()` method. ```javascript -mongoose.connect('mongodb://localhost:27017/myapp'); +mongoose.connect('mongodb://127.0.0.1:27017/myapp'); ``` This is the minimum needed to connect the `myapp` database running locally @@ -16,7 +16,7 @@ You can also specify several more parameters in the `uri`: mongoose.connect('mongodb://username:password@host:port/database?options...'); ``` -See the [mongodb connection string spec](http://docs.mongodb.org/manual/reference/connection-string/) for more details. +See the [mongodb connection string spec](http://www.mongodb.com/docs/manual/reference/connection-string/) for more details.

Operation Buffering

@@ -40,7 +39,7 @@ Mongoose lets you start using your models immediately, without waiting for mongoose to establish a connection to MongoDB. ```javascript -mongoose.connect('mongodb://localhost:27017/myapp'); +mongoose.connect('mongodb://127.0.0.1:27017/myapp'); const MyModel = mongoose.model('Test', new Schema({ name: String })); // Works MyModel.findOne(function(error, result) { /* ... */ }); @@ -57,11 +56,11 @@ const MyModel = mongoose.model('Test', new Schema({ name: String })); MyModel.findOne(function(error, result) { /* ... */ }); setTimeout(function() { - mongoose.connect('mongodb://localhost:27017/myapp'); + mongoose.connect('mongodb://127.0.0.1:27017/myapp'); }, 60000); ``` -To disable buffering, turn off the [`bufferCommands` option on your schema](./guide.html#bufferCommands). +To disable buffering, turn off the [`bufferCommands` option on your schema](guide.html#bufferCommands). If you have `bufferCommands` on and your connection is hanging, try turning `bufferCommands` off to see if you haven't opened a connection properly. You can also disable `bufferCommands` globally: @@ -71,11 +70,11 @@ mongoose.set('bufferCommands', false); ``` Note that buffering is also responsible for waiting until Mongoose -creates collections if you use the [`autoCreate` option](/docs/guide.html#autoCreate). +creates collections if you use the [`autoCreate` option](guide.html#autoCreate). If you disable buffering, you should also disable the `autoCreate` -option and use [`createCollection()`](/docs/api/model.html#model_Model-createCollection) -to create [capped collections](/docs/guide.html#capped) or -[collections with collations](/docs/guide.html#collation). +option and use [`createCollection()`](api/model.html#model_Model-createCollection) +to create [capped collections](guide.html#capped) or +[collections with collations](guide.html#collation). ```javascript const schema = new Schema({ @@ -102,12 +101,12 @@ There are two classes of errors that can occur with a Mongoose connection. To handle initial connection errors, you should use `.catch()` or `try/catch` with async/await. ```javascript -mongoose.connect('mongodb://localhost:27017/test'). +mongoose.connect('mongodb://127.0.0.1:27017/test'). catch(error => handleError(error)); // Or: try { - await mongoose.connect('mongodb://localhost:27017/test'); + await mongoose.connect('mongodb://127.0.0.1:27017/test'); } catch (error) { handleError(error); } @@ -139,7 +138,7 @@ A full list of options can be found on the [MongoDB Node.js driver docs for `Mon Mongoose passes options to the driver without modification, modulo a few exceptions that are explained below. -* `bufferCommands` - This is a mongoose-specific option (not passed to the MongoDB driver) that disables [Mongoose's buffering mechanism](http://mongoosejs.com/docs/faq.html#callback_never_executes) +* `bufferCommands` - This is a mongoose-specific option (not passed to the MongoDB driver) that disables [Mongoose's buffering mechanism](faq.html#callback_never_executes) * `user`/`pass` - The username and password for authentication. These options are Mongoose-specific, they are equivalent to the MongoDB driver's `auth.username` and `auth.password` options. * `autoIndex` - By default, mongoose will automatically build indexes defined in your schema when it connects. This is great for development, but not ideal for large production deployments, because index builds can cause performance degradation. If you set `autoIndex` to false, mongoose will not automatically build indexes for **any** model associated with this connection. * `dbName` - Specifies which database to connect to and overrides any database specified in the connection string. This is useful if you are unable to specify a default database in the connection string like with [some `mongodb+srv` syntax connections](https://stackoverflow.com/questions/48917591/fail-to-connect-mongoose-to-atlas/48917626#48917626). @@ -147,11 +146,11 @@ exceptions that are explained below. Below are some of the options that are important for tuning Mongoose. * `promiseLibrary` - Sets the [underlying driver's promise library](http://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html). -* `maxPoolSize` - The maximum number of sockets the MongoDB driver will keep open for this connection. By default, `maxPoolSize` is 100. Keep in mind that MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](http://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs). You may want to decrease `maxPoolSize` if you are running into [connection limits](https://docs.atlas.mongodb.com/reference/atlas-limits/#connection-limits-and-cluster-tier). +* `maxPoolSize` - The maximum number of sockets the MongoDB driver will keep open for this connection. By default, `maxPoolSize` is 100. Keep in mind that MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](http://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs). You may want to decrease `maxPoolSize` if you are running into [connection limits](https://www.mongodb.com/docs/atlas/reference/atlas-limits/#connection-limits-and-cluster-tier). * `minPoolSize` - The minimum number of sockets the MongoDB driver will keep open for this connection. The MongoDB driver may close sockets that have been inactive for some time. You may want to increase `minPoolSize` if you expect your app to go through long idle times and want to make sure your sockets stay open to avoid slow trains when activity picks up. * `socketTimeoutMS` - How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes. * `family` - Whether to connect using IPv4 or IPv6. This option passed to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. If you don't specify this option, the MongoDB driver will try IPv6 first and then IPv4 if IPv6 fails. If your `mongoose.connect(uri)` call takes a long time, try `mongoose.connect(uri, { family: 4 })` -* `authSource` - The database to use when authenticating with `user` and `pass`. In MongoDB, [users are scoped to a database](https://docs.mongodb.com/manual/tutorial/manage-users-and-roles/). If you are getting an unexpected login failure, you may need to set this option. +* `authSource` - The database to use when authenticating with `user` and `pass`. In MongoDB, [users are scoped to a database](https://www.mongodb.com/docs/manual/tutorial/manage-users-and-roles/). If you are getting an unexpected login failure, you may need to set this option. * `serverSelectionTimeoutMS` - The MongoDB driver will try to find a server to send any given operation to, and keep retrying for `serverSelectionTimeoutMS` milliseconds. If not set, the MongoDB driver defaults to using `30000` (30 seconds). * `heartbeatFrequencyMS` - The MongoDB driver sends a heartbeat every `heartbeatFrequencyMS` to check on the status of the connection. A heartbeat is subject to `serverSelectionTimeoutMS`, so the MongoDB driver will retry failed heartbeats for up to 30 seconds by default. Mongoose only emits a `'disconnected'` event after a heartbeat has failed, so you may want to decrease this setting to reduce the time between when your server goes down and when Mongoose emits `'disconnected'`. We recommend you do **not** set this setting below 1000, too many heartbeats can lead to performance degradation. @@ -179,7 +178,7 @@ See [this page](http://mongodb.github.io/node-mongodb-native/3.1/reference/faq/)

Callback

The `connect()` function also accepts a callback parameter and returns a -[promise](./promises.html). +[promise](promises.html). ```javascript mongoose.connect(uri, options, function(error) { @@ -202,9 +201,9 @@ driver. You **can't** set Mongoose-specific options like `bufferCommands` in the query string. ```javascript -mongoose.connect('mongodb://localhost:27017/test?connectTimeoutMS=1000&bufferCommands=false&authSource=otherdb'); +mongoose.connect('mongodb://127.0.0.1:27017/test?connectTimeoutMS=1000&bufferCommands=false&authSource=otherdb'); // The above is equivalent to: -mongoose.connect('mongodb://localhost:27017/test', { +mongoose.connect('mongodb://127.0.0.1:27017/test', { connectTimeoutMS: 1000 // Note that mongoose will **not** pull `bufferCommands` from the query string }); @@ -219,11 +218,11 @@ or `ssl`, in the connection string, and options that should remain constant, like `connectTimeoutMS` or `maxPoolSize`, in the options object. The MongoDB docs have a full list of -[supported connection string options](https://docs.mongodb.com/manual/reference/connection-string/). +[supported connection string options](https://www.mongodb.com/docs/manual/reference/connection-string/). Below are some options that are often useful to set in the connection string because they are closely associated with the hostname and authentication information. -* `authSource` - The database to use when authenticating with `user` and `pass`. In MongoDB, [users are scoped to a database](https://docs.mongodb.com/manual/tutorial/manage-users-and-roles/). If you are getting an unexpected login failure, you may need to set this option. +* `authSource` - The database to use when authenticating with `user` and `pass`. In MongoDB, [users are scoped to a database](https://www.mongodb.com/docs/manual/tutorial/manage-users-and-roles/). If you are getting an unexpected login failure, you may need to set this option. * `family` - Whether to connect using IPv4 or IPv6. This option passed to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. If you don't specify this option, the MongoDB driver will try IPv6 first and then IPv4 if IPv6 fails. If your `mongoose.connect(uri)` call takes a long time, try `mongoose.connect(uri, { family: 4 })`

Connection Events

@@ -236,11 +235,11 @@ connection may emit. * `connecting`: Emitted when Mongoose starts making its initial connection to the MongoDB server * `connected`: Emitted when Mongoose successfully makes its initial connection to the MongoDB server, or when Mongoose reconnects after losing connectivity. May be emitted multiple times if Mongoose loses connectivity. * `open`: Emitted after `'connected'` and `onOpen` is executed on all of this connection's models. -* `disconnecting`: Your app called [`Connection#close()`](api.html#connection_Connection-close) to disconnect from MongoDB +* `disconnecting`: Your app called [`Connection#close()`](api/connection.html#connection_Connection-close) to disconnect from MongoDB * `disconnected`: Emitted when Mongoose lost connection to the MongoDB server. This event may be due to your code explicitly closing the connection, the database server crashing, or network connectivity issues. -* `close`: Emitted after [`Connection#close()`](api.html#connection_Connection-close) successfully closes the connection. If you call `conn.close()`, you'll get both a 'disconnected' event and a 'close' event. +* `close`: Emitted after [`Connection#close()`](api/connection.html#connection_Connection-close) successfully closes the connection. If you call `conn.close()`, you'll get both a 'disconnected' event and a 'close' event. * `reconnected`: Emitted if Mongoose lost connectivity to MongoDB and successfully reconnected. Mongoose attempts to [automatically reconnect](https://thecodebarbarian.com/managing-connections-with-the-mongodb-node-driver.html) when it loses connection to the database. -* `error`: Emitted if an error occurs on a connection, like a `parseError` due to malformed data or a payload larger than [16MB](https://docs.mongodb.com/manual/reference/limits/#BSON-Document-Size). +* `error`: Emitted if an error occurs on a connection, like a `parseError` due to malformed data or a payload larger than [16MB](https://www.mongodb.com/docs/manual/reference/limits/#BSON-Document-Size). * `fullsetup`: Emitted when you're connecting to a replica set and Mongoose has successfully connected to the primary and at least one secondary. * `all`: Emitted when you're connecting to a replica set and Mongoose has successfully connected to all servers specified in your connection string. @@ -254,7 +253,7 @@ For long running applications, it is often prudent to enable `keepAlive` with a number of milliseconds. Without it, after some period of time you may start to see `"connection closed"` errors for what seems like no reason. If so, after -[reading this](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html), +[reading this](https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html), you may decide to enable `keepAlive`: ```javascript @@ -333,8 +332,8 @@ This can cause confusing errors if you're connecting to a remote MongoDB replica MongooseServerSelectionError: connect ECONNREFUSED localhost:27017 ``` -If you're experiencing a similar error, connect to the replica set using the `mongo` shell and run the [`rs.conf()`](https://docs.mongodb.com/manual/reference/method/rs.conf/) command to check the host names of each replica set member. -Follow [this page's instructions to change a replica set member's host name](https://docs.mongodb.com/manual/tutorial/change-hostnames-in-a-replica-set/#change-hostnames-while-maintaining-replica-set-availability). +If you're experiencing a similar error, connect to the replica set using the `mongo` shell and run the [`rs.conf()`](https://www.mongodb.com/docs/manual/reference/method/rs.conf/) command to check the host names of each replica set member. +Follow [this page's instructions to change a replica set member's host name](https://www.mongodb.com/docs/manual/tutorial/change-hostnames-in-a-replica-set/#change-hostnames-while-maintaining-replica-set-availability). You can also check the `reason.servers` property of `MongooseServerSelectionError` to see what the MongoDB Node driver thinks the state of your replica set is. The `reason.servers` property contains a [map](https://masteringjs.io/tutorials/fundamentals/map) of server descriptions. @@ -355,7 +354,7 @@ if (err.name === 'MongooseServerSelectionError') {

Multi-mongos support

-You can also connect to multiple [mongos](https://docs.mongodb.com/manual/reference/program/mongos/) instances +You can also connect to multiple [mongos](https://www.mongodb.com/docs/manual/reference/program/mongos/) instances for high availability in a sharded cluster. You do [not need to pass any special options to connect to multiple mongos](http://mongodb.github.io/node-mongodb-native/3.0/tutorials/connect/#connect-to-sharded-cluster) in mongoose 5.x. @@ -380,8 +379,8 @@ The `mongoose.createConnection()` function takes the same arguments as const conn = mongoose.createConnection('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options); ``` -This [connection](./api.html#connection_Connection) object is then used to -create and retrieve [models](./api.html#model_Model). Models are +This [connection](api/connection.html#connection_Connection) object is then used to +create and retrieve [models](api/model.html#model_Model). Models are **always** scoped to a single connection. ```javascript @@ -454,10 +453,10 @@ using your connection options: mongoose.createConnection(uri, { maxPoolSize: 10 }); // With connection string options -const uri = 'mongodb://localhost:27017/test?maxPoolSize=10'; +const uri = 'mongodb://127.0.0.1:27017/test?maxPoolSize=10'; mongoose.createConnection(uri); ```

Next Up

-Now that we've covered connections, let's take a look at [models](/docs/models.html). +Now that we've covered connections, let's take a look at [models](models.html). diff --git a/docs/defaults.md b/docs/defaults.md index 104eed4e94e..422643e2748 100644 --- a/docs/defaults.md +++ b/docs/defaults.md @@ -23,7 +23,7 @@ execute that function and use the return value as the default. ### The `setDefaultsOnInsert` Option -Mongoose also sets defaults on `update()` and `findOneAndUpdate()` when the `upsert` option is set by adding your schema's defaults to a [MongoDB `$setOnInsert` operator](https://docs.mongodb.org/manual/reference/operator/update/setOnInsert/). +Mongoose also sets defaults on `update()` and `findOneAndUpdate()` when the `upsert` option is set by adding your schema's defaults to a [MongoDB `$setOnInsert` operator](https://www.mongodb.com/docs/manual/reference/operator/update/setOnInsert/). You can disable this behavior by setting the `setDefaultsOnInsert` option to `false`. ```javascript diff --git a/docs/deprecations.md b/docs/deprecations.md index 14aaaf35465..54745af44cd 100644 --- a/docs/deprecations.md +++ b/docs/deprecations.md @@ -28,7 +28,7 @@ deleteMany, or bulkWrite instead. ``` To remove this deprecation warning, replace any usage of `remove()` with -`deleteMany()`, _unless_ you specify the [`single` option to `remove()`](/docs/api.html#model_Model-remove). The `single` +`deleteMany()`, _unless_ you specify the [`single` option to `remove()`](api/model.html#model_Model-remove). The `single` option limited `remove()` to deleting at most one document, so you should replace `remove(filter, { single: true })` with `deleteOne(filter)`. @@ -46,9 +46,9 @@ MyModel.deleteOne({ answer: 42 });

update()

-Like `remove()`, the [`update()` function](/docs/api.html#model_Model-update) is deprecated in favor -of the more explicit [`updateOne()`](/docs/api.html#model_Model-updateOne), [`updateMany()`](/docs/api.html#model_Model-updateMany), and [`replaceOne()`](/docs/api.html#model_Model-replaceOne) functions. You should replace -`update()` with `updateOne()`, unless you use the [`multi` or `overwrite` options](/docs/api.html#model_Model-update). +Like `remove()`, the [`update()` function](api/model.html#model_Model-update) is deprecated in favor +of the more explicit [`updateOne()`](api/model.html#model_Model-updateOne), [`updateMany()`](api/model.html#model_Model-updateMany), and [`replaceOne()`](api/model.html#model_Model-replaceOne) functions. You should replace +`update()` with `updateOne()`, unless you use the [`multi` or `overwrite` options](api/model.html#model_Model-update). ``` collection.update is deprecated. Use updateOne, updateMany, or bulkWrite diff --git a/docs/discriminators.md b/docs/discriminators.md index 72fdda371c1..e97e4ad1373 100644 --- a/docs/discriminators.md +++ b/docs/discriminators.md @@ -31,12 +31,25 @@ instances. ### Discriminator keys -The way mongoose tells the difference between the different -discriminator models is by the 'discriminator key', which is -`__t` by default. Mongoose adds a String path called `__t` -to your schemas that it uses to track which discriminator -this document is an instance of. +The way Mongoose tells the difference between the different discriminator models is by the 'discriminator key', which is `__t` by default. +Mongoose adds a String path called `__t` to your schemas that it uses to track which discriminator this document is an instance of. ```javascript [require:Discriminator keys] ``` + +### Updating the discriminator key + +By default, Mongoose doesn't let you update the discriminator key. +`save()` will throw an error if you attempt to update the discriminator key. +And `findOneAndUpdate()`, `updateOne()`, etc. will strip out discriminator key updates. + +```javascript +[require:Update discriminator key] +``` + +To update a document's discriminator key, use `findOneAndUpdate()` or `updateOne()` with the `overwriteDiscriminatorKey` option set as follows. + +```javascript +[require:use overwriteDiscriminatorKey to change discriminator key] +``` \ No newline at end of file diff --git a/docs/documents.md b/docs/documents.md index a1b909ffeac..d95c7217a7e 100644 --- a/docs/documents.md +++ b/docs/documents.md @@ -1,8 +1,8 @@ ## Documents -Mongoose [documents](./api/document.html) represent a one-to-one mapping +Mongoose [documents](api/document.html) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its -[Model](./models.html). +[Model](models.html).