diff --git a/.changeset/cool-bees-joke.md b/.changeset/cool-bees-joke.md new file mode 100644 index 00000000000..32b8f361caa --- /dev/null +++ b/.changeset/cool-bees-joke.md @@ -0,0 +1,5 @@ +--- +'@keystonejs/adapter-mongoose': patch +--- + +Uses the new `mongo-join-builder` API. diff --git a/.changeset/olive-mails-do.md b/.changeset/olive-mails-do.md new file mode 100644 index 00000000000..febc473c4be --- /dev/null +++ b/.changeset/olive-mails-do.md @@ -0,0 +1,5 @@ +--- +'@keystonejs/mongo-join-builder': major +--- + +Removed the `mutationBuilder` function in favour of using `$project` operations in the main pipeline. diff --git a/packages/adapter-mongoose/lib/adapter-mongoose.js b/packages/adapter-mongoose/lib/adapter-mongoose.js index 40ba2691f4f..57921a0db0c 100644 --- a/packages/adapter-mongoose/lib/adapter-mongoose.js +++ b/packages/adapter-mongoose/lib/adapter-mongoose.js @@ -13,7 +13,7 @@ const { } = require('@keystonejs/utils'); const { BaseKeystoneAdapter, BaseListAdapter, BaseFieldAdapter } = require('@keystonejs/keystone'); -const { queryParser, pipelineBuilder, mutationBuilder } = require('@keystonejs/mongo-join-builder'); +const { queryParser, pipelineBuilder } = require('@keystonejs/mongo-join-builder'); const logger = require('@keystonejs/logger').logger('mongoose'); const slugify = require('@sindresorhus/slugify'); @@ -249,7 +249,6 @@ class MongooseListAdapter extends BaseListAdapter { return this.model .aggregate(pipelineBuilder(queryTree)) .exec() - .then(mutationBuilder(queryTree.relationships)) .then(foundItems => { if (meta) { // When there are no items, we get undefined back, so we simulate the diff --git a/packages/adapter-mongoose/package.json b/packages/adapter-mongoose/package.json index 41d5daffa32..5ac6e32284d 100644 --- a/packages/adapter-mongoose/package.json +++ b/packages/adapter-mongoose/package.json @@ -14,7 +14,6 @@ "@keystonejs/mongo-join-builder": "^5.0.2", "@keystonejs/utils": "^5.1.3", "@sindresorhus/slugify": "^0.6.0", - "lodash.omitby": "^4.6.0", "mongoose": "^5.8.4", "p-settle": "^3.1.0", "pluralize": "^7.0.0" diff --git a/packages/adapter-mongoose/tests/list-adapter.test.js b/packages/adapter-mongoose/tests/list-adapter.test.js index 2b1d4068312..87d98775479 100644 --- a/packages/adapter-mongoose/tests/list-adapter.test.js +++ b/packages/adapter-mongoose/tests/list-adapter.test.js @@ -81,7 +81,7 @@ describe('MongooseListAdapter', () => { }, { $match: { $and: [expect.any(Object), { title: { $eq: 'bar' } }] } }, { $addFields: { id: '$_id' } }, - { $project: { posts: 0 } }, + { $project: expect.any(Object) }, ]); await userListAdapter.itemsQuery({ @@ -104,7 +104,7 @@ describe('MongooseListAdapter', () => { }, { $match: { $or: [expect.any(Object), { title: { $eq: 'bar' } }] } }, { $addFields: { id: '$_id' } }, - { $project: { posts: 0 } }, + { $project: expect.any(Object) }, ]); }); @@ -167,7 +167,7 @@ describe('MongooseListAdapter', () => { }, { $match: expect.any(Object) }, { $addFields: { id: '$_id' } }, - { $project: { posts: 0 } }, + { $project: expect.any(Object) }, ]); await userListAdapter.itemsQuery({ @@ -190,7 +190,7 @@ describe('MongooseListAdapter', () => { }, { $match: expect.any(Object) }, { $addFields: { id: '$_id' } }, - { $project: { posts: 0 } }, + { $project: expect.any(Object) }, ]); }); }); diff --git a/packages/fields/src/types/DateTime/README.md b/packages/fields/src/types/DateTime/README.md index b20744ca6a0..fdc9c20b580 100644 --- a/packages/fields/src/types/DateTime/README.md +++ b/packages/fields/src/types/DateTime/README.md @@ -26,14 +26,14 @@ keystone.createList('User', { ### Config -| Option | Type | Default | Description | -| ---------------- | --------- | ---------------------- | -------------------------------------------------------------------------- | -| `format` | `String` | `--` | Defines the format of the string that the component generates | -| `yearRangeFrom` | `String` | The current year - 100 | Defines the starting point of the year range, e.g. `1918` | +| Option | Type | Default | Description | +| ---------------- | --------- | ---------------------- | --------------------------------------------------------------------------- | +| `format` | `String` | `--` | Defines the format of the string that the component generates | +| `yearRangeFrom` | `String` | The current year - 100 | Defines the starting point of the year range, e.g. `1918` | | `yearRangeTo` | `String` | The current year | Defines the ending point of the range in the yearSelect field , e.g. `2018` | -| `yearPickerType` | `String` | `auto` | Defines the input type for the year selector | -| `isRequired` | `Boolean` | `false` | Does this field require a value? | -| `isUnique` | `Boolean` | `false` | Adds a unique index that allows only unique values to be stored | +| `yearPickerType` | `String` | `auto` | Defines the input type for the year selector | +| `isRequired` | `Boolean` | `false` | Does this field require a value? | +| `isUnique` | `Boolean` | `false` | Adds a unique index that allows only unique values to be stored | #### `format` diff --git a/packages/file-adapters/README.md b/packages/file-adapters/README.md index 679d46a0e81..6740db2dbc3 100644 --- a/packages/file-adapters/README.md +++ b/packages/file-adapters/README.md @@ -116,15 +116,15 @@ const fileAdapter = new S3Adapter({ }); ``` -| Option | Type | Default | Description | -| ----------------- | ----------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `accessKeyId` | `String` | Required | AWS access key ID | -| `secretAccessKey` | `String` | Required | AWS secret access key | -| `region` | `String` | Required | AWS region | -| `bucket` | `String` | Required | S3 bucket name | -| `folder` | `String` | Required | Upload folder from root of bucket | -| `publicUrl` | `Function` | | By default the publicUrl returns a url for the S3 bucket in the form `https://{bucket}.s3.amazonaws.com/{key}/{filename}`. This will only work if the bucket is configured to allow public access. | -| `s3Options` | `Object` | `undefined` | For available options refer to the [AWS S3 API](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) | +| Option | Type | Default | Description | +| ----------------- | ----------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `accessKeyId` | `String` | Required | AWS access key ID | +| `secretAccessKey` | `String` | Required | AWS secret access key | +| `region` | `String` | Required | AWS region | +| `bucket` | `String` | Required | S3 bucket name | +| `folder` | `String` | Required | Upload folder from root of bucket | +| `publicUrl` | `Function` | | By default the publicUrl returns a url for the S3 bucket in the form `https://{bucket}.s3.amazonaws.com/{key}/{filename}`. This will only work if the bucket is configured to allow public access. | +| `s3Options` | `Object` | `undefined` | For available options refer to the [AWS S3 API](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) | | `uploadParams` | `Object|Function` | `{}` | A config object or function returning a config object to be passed with each call to S3.upload. For available options refer to the [AWS S3 upload API](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property). | ### Methods diff --git a/packages/mongo-join-builder/examples/nested-relationship/index.js b/packages/mongo-join-builder/examples/nested-relationship/index.js index 37c1ebaabdc..56eec056ef4 100644 --- a/packages/mongo-join-builder/examples/nested-relationship/index.js +++ b/packages/mongo-join-builder/examples/nested-relationship/index.js @@ -1,12 +1,11 @@ -const { queryParser, pipelineBuilder, mutationBuilder } = require('../../'); +const { queryParser, pipelineBuilder } = require('../../'); const getDatabase = require('../database'); const builder = async (query, aggregate, listAdapter) => { const queryTree = queryParser({ listAdapter }, query); const pipeline = pipelineBuilder(queryTree); - const postQueryMutations = mutationBuilder(queryTree.relationships); // Run the query against the given database and collection - return await aggregate(pipeline).then(postQueryMutations); + return await aggregate(pipeline); }; // Get all unfulfilled orders that have some out of stock items diff --git a/packages/mongo-join-builder/examples/relationship/index.js b/packages/mongo-join-builder/examples/relationship/index.js index 149e79f82f0..c473e6342ec 100644 --- a/packages/mongo-join-builder/examples/relationship/index.js +++ b/packages/mongo-join-builder/examples/relationship/index.js @@ -1,11 +1,10 @@ -const { queryParser, pipelineBuilder, mutationBuilder } = require('../../'); +const { queryParser, pipelineBuilder } = require('../../'); const getDatabase = require('../database'); const builder = async (query, aggregate, listAdapter) => { const queryTree = queryParser({ listAdapter }, query); const pipeline = pipelineBuilder(queryTree); - const postQueryMutations = mutationBuilder(queryTree.relationships); // Run the query against the given database and collection - return await aggregate(pipeline).then(postQueryMutations); + return await aggregate(pipeline); }; const query = { diff --git a/packages/mongo-join-builder/index.js b/packages/mongo-join-builder/index.js index f305d02a394..38345ae2911 100644 --- a/packages/mongo-join-builder/index.js +++ b/packages/mongo-join-builder/index.js @@ -1,8 +1,4 @@ const { queryParser } = require('./lib/query-parser'); -const { pipelineBuilder, mutationBuilder } = require('./lib/join-builder'); +const { pipelineBuilder } = require('./lib/join-builder'); -module.exports = { - queryParser, - pipelineBuilder, - mutationBuilder, -}; +module.exports = { queryParser, pipelineBuilder }; diff --git a/packages/mongo-join-builder/lib/join-builder.js b/packages/mongo-join-builder/lib/join-builder.js index f11021ae6f0..fa55fb46cca 100644 --- a/packages/mongo-join-builder/lib/join-builder.js +++ b/packages/mongo-join-builder/lib/join-builder.js @@ -1,5 +1,4 @@ -const omitBy = require('lodash.omitby'); -const { flatten, compose, defaultObj } = require('@keystonejs/utils'); +const { flatten, defaultObj } = require('@keystonejs/utils'); /** * Format of input object: @@ -43,47 +42,6 @@ const { flatten, compose, defaultObj } = require('@keystonejs/utils'); ], } */ -function mutation(uid, lookupPath) { - return queryResult => { - function mutate(arrayToMutate, lookupPathFragment, pathSoFar = []) { - const [keyToMutate, ...restOfLookupPath] = lookupPathFragment; - - return arrayToMutate.map((value, index) => { - if (!(keyToMutate in value)) { - return value; - } - - if (restOfLookupPath.length === 0) { - // Now we can execute the mutation - return omitBy(value, (_, keyToOmit) => keyToOmit.startsWith(uid)); - } - - // Recurse - return { - ...value, - [keyToMutate]: mutate(value[keyToMutate], restOfLookupPath, [ - ...pathSoFar, - index, - keyToMutate, - ]), - }; - }); - } - - return mutate(queryResult, lookupPath); - }; -} - -function mutationBuilder(relationships, path = []) { - return compose( - Object.entries(relationships).map(([uid, { relationshipInfo, relationships }]) => { - const { uniqueField } = relationshipInfo; - const postQueryMutations = mutationBuilder(relationships, [...path, uniqueField]); - // NOTE: Order is important. We want depth first, so we perform the related mutators first. - return compose([postQueryMutations, mutation(uid, [...path, uniqueField])]); - }) - ); -} function relationshipPipeline(relationship) { const { field, many, from, uniqueField } = relationship.relationshipInfo; @@ -108,8 +66,9 @@ function relationshipPipeline(relationship) { } function pipelineBuilder({ relationships, matchTerm, excludeFields, postJoinPipeline }) { + excludeFields.push(...relationships.map(({ relationshipInfo }) => relationshipInfo.uniqueField)); return [ - ...flatten(Object.values(relationships).map(relationshipPipeline)), + ...flatten(relationships.map(relationshipPipeline)), matchTerm && { $match: matchTerm }, { $addFields: { id: '$_id' } }, excludeFields && excludeFields.length && { $project: defaultObj(excludeFields, 0) }, @@ -117,4 +76,4 @@ function pipelineBuilder({ relationships, matchTerm, excludeFields, postJoinPipe ].filter(i => i); } -module.exports = { pipelineBuilder, mutationBuilder }; +module.exports = { pipelineBuilder }; diff --git a/packages/mongo-join-builder/lib/query-parser.js b/packages/mongo-join-builder/lib/query-parser.js index 573a4f07415..4af8dd82816 100644 --- a/packages/mongo-join-builder/lib/query-parser.js +++ b/packages/mongo-join-builder/lib/query-parser.js @@ -1,5 +1,5 @@ const cuid = require('cuid'); -const { getType, flatten, objMerge } = require('@keystonejs/utils'); +const { getType, flatten } = require('@keystonejs/utils'); const { simpleTokenizer, relationshipTokenizer, modifierTokenizer } = require('./tokenizers'); @@ -13,7 +13,7 @@ const flattenQueries = (parsedQueries, joinOp) => ({ joinOp ), postJoinPipeline: flatten(parsedQueries.map(q => q.postJoinPipeline || [])).filter(pipe => pipe), - relationships: objMerge(parsedQueries.map(q => q.relationships || {})), + relationships: flatten(parsedQueries.map(q => q.relationships || [])), }); function queryParser({ listAdapter, getUID = cuid }, query, pathSoFar = [], include) { @@ -44,21 +44,18 @@ function queryParser({ listAdapter, getUID = cuid }, query, pathSoFar = [], incl } } else if (getType(value) === 'Object') { // A relationship query component - const uid = getUID(key); const { matchTerm, relationshipInfo } = relationshipTokenizer( listAdapter, query, key, path, - uid + getUID(key) ); return { // matchTerm is our filtering expression. This determines if the // parent item is included in the final list matchTerm, - relationships: { - [uid]: { relationshipInfo, ...queryParser({ listAdapter, getUID }, value, path) }, - }, + relationships: [{ relationshipInfo, ...queryParser({ listAdapter, getUID }, value, path) }], }; } else { // A simple field query component @@ -66,7 +63,7 @@ function queryParser({ listAdapter, getUID = cuid }, query, pathSoFar = [], incl } }); const flatQueries = flattenQueries(parsedQueries, '$and'); - const includeFields = Object.values(flatQueries.relationships).map(({ field }) => field); + const includeFields = flatQueries.relationships.map(({ field }) => field); if (include) includeFields.push(include); return { diff --git a/packages/mongo-join-builder/package.json b/packages/mongo-join-builder/package.json index c444b1b9c3b..9118fdb5e20 100644 --- a/packages/mongo-join-builder/package.json +++ b/packages/mongo-join-builder/package.json @@ -9,8 +9,7 @@ }, "dependencies": { "@keystonejs/utils": "^5.1.3", - "cuid": "^2.1.6", - "lodash.omitby": "^4.6.0" + "cuid": "^2.1.6" }, "devDependencies": { "mongodb": "^3.4.1", diff --git a/packages/mongo-join-builder/tests/index.test.js b/packages/mongo-join-builder/tests/index.test.js index 4ceb7927f1d..84059d86eae 100644 --- a/packages/mongo-join-builder/tests/index.test.js +++ b/packages/mongo-join-builder/tests/index.test.js @@ -1,4 +1,4 @@ -const { queryParser, pipelineBuilder, mutationBuilder } = require('../'); +const { queryParser, pipelineBuilder } = require('../'); const { listAdapter } = require('./utils'); describe('Test main export', () => { @@ -56,10 +56,9 @@ describe('Test main export', () => { }, ]; const pipeline = pipelineBuilder(queryTree); - const postQueryMutations = mutationBuilder(queryTree.relationships); const aggregate = jest.fn(() => Promise.resolve(aggregateResponse)); - const result = await aggregate(pipeline).then(postQueryMutations); + const result = await aggregate(pipeline); expect(pipeline).toMatchObject([ { $lookup: { @@ -89,6 +88,7 @@ describe('Test main export', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { tags_some_tags: 0 } }, ], }, }, @@ -106,6 +106,7 @@ describe('Test main export', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { posts_every_posts: 0 } }, ]); expect(result).toMatchObject([ diff --git a/packages/mongo-join-builder/tests/join-builder.test.js b/packages/mongo-join-builder/tests/join-builder.test.js index 05356832bcf..11a3895e978 100644 --- a/packages/mongo-join-builder/tests/join-builder.test.js +++ b/packages/mongo-join-builder/tests/join-builder.test.js @@ -1,4 +1,4 @@ -const { pipelineBuilder, mutationBuilder } = require('../lib/join-builder'); +const { pipelineBuilder } = require('../lib/join-builder'); describe('join builder', () => { test('correctly generates joins for simple queries', () => { @@ -14,7 +14,8 @@ describe('join builder', () => { const pipeline = pipelineBuilder({ matchTerm: { $and: [{ name: { $eq: 'foobar' } }, { age: { $eq: 23 } }] }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }); expect(pipeline).toMatchObject([ @@ -37,8 +38,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - abc123: { + relationships: [ + { matchTerm: { name: { $eq: 'Alice' } }, relationshipInfo: { from: 'user-collection', @@ -46,10 +47,11 @@ describe('join builder', () => { many: false, uniqueField: 'abc123_author', }, + excludeFields: [], postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], matchTerm: { $and: [ { title: { $eq: 'foobar' } }, @@ -57,6 +59,7 @@ describe('join builder', () => { { $expr: { $eq: [{ $size: '$abc123_author' }, 1] } }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -83,6 +86,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { abc123_author: 0 } }, ]); }); @@ -98,8 +102,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - abc123: { + relationships: [ + { relationshipInfo: { from: 'posts-collection', field: 'posts', @@ -107,9 +111,10 @@ describe('join builder', () => { uniqueField: 'abc123_posts', }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -117,6 +122,7 @@ describe('join builder', () => { { $expr: { $gt: [{ $size: '$abc123_posts' }, 0] } }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -142,6 +148,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { abc123_posts: 0 } }, ]); }); @@ -157,8 +164,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - abc123: { + relationships: [ + { relationshipInfo: { from: 'posts-collection', field: 'posts', @@ -166,9 +173,10 @@ describe('join builder', () => { uniqueField: 'abc123_posts', }, postJoinPipeline: [{ $orderBy: 'title' }], - relationships: {}, + relationships: [], + excludeFields: [], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -176,6 +184,7 @@ describe('join builder', () => { { $expr: { $eq: [{ $size: '$abc123_posts' }, { $size: { $ifNull: ['$posts', []] } }] } }, ], }, + excludeFields: [], postJoinPipeline: [{ $limit: 10 }], }); @@ -204,6 +213,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { abc123_posts: 0 } }, { $limit: 10 }, ]); }); @@ -228,8 +238,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - abc123: { + relationships: [ + { matchTerm: { $and: [{ title: { $eq: 'hello' } }, { $expr: { $gt: [{ $size: '$def456_tags' }, 0] } }], }, @@ -240,8 +250,9 @@ describe('join builder', () => { uniqueField: 'abc123_posts', }, postJoinPipeline: [], - relationships: { - def456: { + excludeFields: [], + relationships: [ + { matchTerm: { $and: [ { name: { $eq: 'React' } }, @@ -259,8 +270,9 @@ describe('join builder', () => { uniqueField: 'def456_tags', }, postJoinPipeline: [], - relationships: { - xyz890: { + excludeFields: [], + relationships: [ + { matchTerm: { published: { $eq: true } }, relationshipInfo: { from: 'posts-collection', @@ -269,13 +281,14 @@ describe('join builder', () => { uniqueField: 'xyz890_posts', }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }, - }, + ], }, - }, + ], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -283,6 +296,7 @@ describe('join builder', () => { { $expr: { $gt: [{ $size: '$abc123_posts' }, 0] } }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -330,6 +344,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { xyz890_posts: 0 } }, ], }, }, @@ -342,6 +357,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { def456_tags: 0 } }, ], }, }, @@ -355,6 +371,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { abc123_posts: 0 } }, ]); }); @@ -376,8 +393,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - zip567: { + relationships: [ + { matchTerm: { $and: [ { title: { $eq: 'hello' } }, @@ -391,8 +408,9 @@ describe('join builder', () => { uniqueField: 'zip567_posts', }, postJoinPipeline: [], - relationships: { - quux987: { + excludeFields: [], + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { from: 'labels-collection', @@ -401,11 +419,12 @@ describe('join builder', () => { uniqueField: 'quux987_labels', }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -417,6 +436,7 @@ describe('join builder', () => { }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -449,6 +469,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { quux987_labels: 0 } }, ], }, }, @@ -466,6 +487,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { zip567_posts: 0 } }, ]); }); @@ -487,8 +509,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - zip567: { + relationships: [ + { matchTerm: { $or: [ { title: { $eq: 'hello' } }, @@ -502,8 +524,9 @@ describe('join builder', () => { uniqueField: 'zip567_posts', }, postJoinPipeline: [], - relationships: { - quux987: { + excludeFields: [], + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { from: 'labels-collection', @@ -512,11 +535,12 @@ describe('join builder', () => { uniqueField: 'quux987_labels', }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $or: [ { name: { $eq: 'foobar' } }, @@ -528,6 +552,7 @@ describe('join builder', () => { }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -562,6 +587,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { quux987_labels: 0 } }, ], }, }, @@ -579,6 +605,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { zip567_posts: 0 } }, ]); }); @@ -600,8 +627,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - zip567: { + relationships: [ + { matchTerm: { $or: [ { title: { $eq: 'hello' } }, @@ -616,8 +643,9 @@ describe('join builder', () => { uniqueField: 'zip567_posts', }, postJoinPipeline: [], - relationships: { - quux987: { + excludeFields: [], + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { from: 'labels-collection', @@ -626,11 +654,12 @@ describe('join builder', () => { uniqueField: 'quux987_labels', }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -642,6 +671,7 @@ describe('join builder', () => { }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -676,6 +706,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { quux987_labels: 0 } }, ], }, }, @@ -693,6 +724,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { zip567_posts: 0 } }, ]); }); @@ -714,8 +746,8 @@ describe('join builder', () => { */ const pipeline = pipelineBuilder({ - relationships: { - zip567: { + relationships: [ + { matchTerm: { $and: [ { title: { $eq: 'hello' } }, @@ -729,8 +761,9 @@ describe('join builder', () => { uniqueField: 'zip567_posts', }, postJoinPipeline: [], - relationships: { - quux987: { + excludeFields: [], + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { from: 'labels-collection', @@ -739,11 +772,12 @@ describe('join builder', () => { uniqueField: 'quux987_labels', }, postJoinPipeline: [], - relationships: {}, + excludeFields: [], + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $or: [ { name: { $eq: 'foobar' } }, @@ -755,6 +789,7 @@ describe('join builder', () => { }, ], }, + excludeFields: [], postJoinPipeline: [], }); @@ -787,6 +822,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { quux987_labels: 0 } }, ], }, }, @@ -804,77 +840,7 @@ describe('join builder', () => { }, }, { $addFields: { id: '$_id' } }, + { $project: { zip567_posts: 0 } }, ]); }); - - test('executes relationship mutators with correct parameters', () => { - // TODO - check it's called with these params: - /* - * From this query: - - { - age: 23, - posts_every: { title: 'hello' }, - } - */ - - const mutationResult = {}; - - const postQueryMutations = mutationBuilder({ - zip567: { - matchTerm: { title: { $eq: 'hello' } }, - - relationshipInfo: { - from: 'posts-collection', - field: 'posts', - many: true, - uniqueField: 'zip567_posts', - }, - postJoinPipeline: [], - relationships: {}, - }, - }); - - /* - { - age: 23, - posts_every: { title: 'hello' }, - } - */ - const mockResult1 = { - age: 23, - name: 'foobar', - zip567_posts: [ - { - title: 'hello', - views: 73, - }, - { - title: 'hello', - views: 57, - }, - ], - }; - - const mockResult2 = { - age: 23, - name: 'quux', - zip567_posts: [ - { - title: 'hello', - views: 123, - }, - { - title: 'hello', - views: 1, - }, - ], - }; - - const mockQueryResult = [mockResult1, mockResult2]; - - const mutatedResult = postQueryMutations(mockQueryResult); - - expect(mutatedResult).toMatchObject([mutationResult, mutationResult]); - }); }); diff --git a/packages/mongo-join-builder/tests/mongo-results.test.js b/packages/mongo-join-builder/tests/mongo-results.test.js index cd90f6b497a..7aa18736d28 100644 --- a/packages/mongo-join-builder/tests/mongo-results.test.js +++ b/packages/mongo-join-builder/tests/mongo-results.test.js @@ -1,4 +1,4 @@ -const { queryParser, pipelineBuilder, mutationBuilder } = require('../'); +const { queryParser, pipelineBuilder } = require('../'); const { postsAdapter, listAdapter } = require('./utils'); const { MongoClient } = require('mongodb'); @@ -8,9 +8,8 @@ const mongoJoinBuilder = parserOptions => { return async (query, aggregate) => { const queryTree = queryParser(parserOptions, query); const pipeline = pipelineBuilder(queryTree); - const postQueryMutations = mutationBuilder(queryTree.relationships); // Run the query against the given database and collection - return await aggregate(pipeline).then(postQueryMutations); + return await aggregate(pipeline); }; }; diff --git a/packages/mongo-join-builder/tests/query-parser.test.js b/packages/mongo-join-builder/tests/query-parser.test.js index 68339983cbd..16152186e54 100644 --- a/packages/mongo-join-builder/tests/query-parser.test.js +++ b/packages/mongo-join-builder/tests/query-parser.test.js @@ -30,7 +30,7 @@ describe('query parser', () => { expect(queryTree).toMatchObject({ // No relationships in this test - relationships: {}, + relationships: [], matchTerm: { $and: [{ name: { $eq: 'foobar' } }, { age: { $eq: 23 } }] }, }); }); @@ -64,7 +64,7 @@ describe('query parser', () => { expect(queryTree).toMatchObject({ // No relationships in this test - relationships: {}, + relationships: [], matchTerm: { $or: [{ name: { $eq: 'foobar' } }, { age: { $eq: 23 } }] }, }); }); @@ -86,8 +86,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts: { + relationships: [ + { matchTerm: { title: { $eq: 'hello' } }, relationshipInfo: { from: 'posts', @@ -96,9 +96,9 @@ describe('query parser', () => { uniqueField: 'posts_posts', }, postJoinPipeline: [{ $sort: { title: 1 } }], - relationships: {}, + relationships: [], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -121,8 +121,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts: { + relationships: [ + { matchTerm: { title: { $eq: 'hello' } }, relationshipInfo: { from: 'posts', @@ -131,9 +131,9 @@ describe('query parser', () => { uniqueField: 'posts_posts', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -155,8 +155,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts: { + relationships: [ + { matchTerm: undefined, relationshipInfo: { from: 'posts', @@ -165,9 +165,9 @@ describe('query parser', () => { uniqueField: 'posts_posts', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -189,8 +189,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - company: { + relationships: [ + { matchTerm: { name: { $eq: 'hello' } }, relationshipInfo: { from: 'company-collection', @@ -199,9 +199,9 @@ describe('query parser', () => { uniqueField: 'company_company', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -229,8 +229,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts_every: { + relationships: [ + { matchTerm: { $and: [ { title: { $eq: 'hello' } }, @@ -244,8 +244,8 @@ describe('query parser', () => { uniqueField: 'posts_every_posts', }, postJoinPipeline: [], - relationships: { - tags_some: { + relationships: [ + { matchTerm: { $and: [ { name: { $eq: 'React' } }, @@ -266,8 +266,8 @@ describe('query parser', () => { uniqueField: 'tags_some_tags', }, postJoinPipeline: [], - relationships: { - posts_every: { + relationships: [ + { matchTerm: { title: { $eq: 'foo' } }, relationshipInfo: { from: 'posts', @@ -276,13 +276,13 @@ describe('query parser', () => { uniqueField: 'posts_every_posts', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], }, - }, + ], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -310,8 +310,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts_every: { + relationships: [ + { matchTerm: { $and: [ { title: { $eq: 'hello' } }, @@ -325,8 +325,8 @@ describe('query parser', () => { uniqueField: 'posts_every_posts', }, postJoinPipeline: [], - relationships: { - tags_some: { + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { field: 'tags', @@ -335,11 +335,11 @@ describe('query parser', () => { uniqueField: 'tags_some_tags', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -367,8 +367,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts_every: { + relationships: [ + { matchTerm: { $or: [ { title: { $eq: 'hello' } }, @@ -382,8 +382,8 @@ describe('query parser', () => { uniqueField: 'posts_every_posts', }, postJoinPipeline: [], - relationships: { - tags_some: { + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { field: 'tags', @@ -392,11 +392,11 @@ describe('query parser', () => { uniqueField: 'tags_some_tags', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $or: [ { name: { $eq: 'foobar' } }, @@ -424,8 +424,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts_every: { + relationships: [ + { matchTerm: { $or: [ { title: { $eq: 'hello' } }, @@ -439,8 +439,8 @@ describe('query parser', () => { uniqueField: 'posts_every_posts', }, postJoinPipeline: [], - relationships: { - tags_some: { + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { field: 'tags', @@ -449,11 +449,11 @@ describe('query parser', () => { uniqueField: 'tags_some_tags', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $and: [ { name: { $eq: 'foobar' } }, @@ -481,8 +481,8 @@ describe('query parser', () => { ); expect(queryTree).toMatchObject({ - relationships: { - posts_every: { + relationships: [ + { matchTerm: { $and: [ { title: { $eq: 'hello' } }, @@ -496,8 +496,8 @@ describe('query parser', () => { uniqueField: 'posts_every_posts', }, postJoinPipeline: [], - relationships: { - tags_some: { + relationships: [ + { matchTerm: { name: { $eq: 'foo' } }, relationshipInfo: { field: 'tags', @@ -506,11 +506,11 @@ describe('query parser', () => { uniqueField: 'tags_some_tags', }, postJoinPipeline: [], - relationships: {}, + relationships: [], }, - }, + ], }, - }, + ], matchTerm: { $or: [ { name: { $eq: 'foobar' } }, diff --git a/yarn.lock b/yarn.lock index 81bdffa6a01..36eb88f545d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14042,11 +14042,6 @@ lodash.mergewith@^4.6.1: resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== -lodash.omitby@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.omitby/-/lodash.omitby-4.6.0.tgz#5c15ff4754ad555016b53c041311e8f079204791" - integrity sha1-XBX/R1StVVAWtTwEExHo8HkgR5E= - lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"