diff --git a/lib/query/hypernova/aggregateFilters.js b/lib/query/hypernova/aggregateSearchFilters.js similarity index 100% rename from lib/query/hypernova/aggregateFilters.js rename to lib/query/hypernova/aggregateSearchFilters.js diff --git a/lib/query/hypernova/assembler.js b/lib/query/hypernova/assembler.js new file mode 100644 index 0000000..b491220 --- /dev/null +++ b/lib/query/hypernova/assembler.js @@ -0,0 +1,25 @@ +import createSearchFilters from './createSearchFilters'; +import sift from 'sift'; + +export default (childCollectionNode) => { + const parent = childCollectionNode.parent; + + const strategy = childCollectionNode.linker.strategy; + const isVirtual = childCollectionNode.linker.isVirtual(); + const fieldStorage = (isVirtual) + ? childCollectionNode.linker.linkConfig.relatedLinker.linkStorageField + : childCollectionNode.linker.linkStorageField; + + _.each(parent.results, result => { + result[childCollectionNode.linkName] = assembleData(childCollectionNode, result, { + fieldStorage, strategy, isVirtual + }) + }) +} + +function assembleData(childCollectionNode, result, {fieldStorage, strategy, isVirtual}) { + + const filters = createSearchFilters(result, fieldStorage, strategy, isVirtual); + + return sift(filters, childCollectionNode.results); +} \ No newline at end of file diff --git a/lib/query/hypernova/hypernova.js b/lib/query/hypernova/hypernova.js index 0d785f5..fb8a20e 100644 --- a/lib/query/hypernova/hypernova.js +++ b/lib/query/hypernova/hypernova.js @@ -1,6 +1,7 @@ import applyProps from '../lib/applyProps.js'; import LinkResolve from '../../links/linkTypes/linkResolve.js'; import storeHypernovaResults from './storeHypernovaResults.js'; +import assembler from './assembler.js'; function hypernova(collectionNode, userId) { _.each(collectionNode.collectionNodes, childCollectionNode => { @@ -15,24 +16,26 @@ function hypernova(collectionNode, userId) { } else { storeHypernovaResults(childCollectionNode, userId); + let start = new Date(); hypernova(childCollectionNode, userId); + let end = new Date(); + console.log(`hypernova: ${end.getTime() - start.getTime()}`); } }); } export default function hypernovaInit(collectionNode, userId) { - let results = []; let {filters, options} = applyProps(collectionNode); const collection = collectionNode.collection; if (collection.findSecure) { - results = collection.findSecure(filters, options, userId).fetch(); + collectionNode.results = collection.findSecure(filters, options, userId).fetch(); } else { - results = collection.find(filters, options).fetch(); + collectionNode.results = collection.find(filters, options).fetch(); } - collectionNode.results = results; + hypernova(collectionNode, userId); - return hypernova(collectionNode, userId); + return collectionNode.results; } diff --git a/lib/query/hypernova/storeHypernovaResults.js b/lib/query/hypernova/storeHypernovaResults.js index 0c255b8..8e9c82b 100644 --- a/lib/query/hypernova/storeHypernovaResults.js +++ b/lib/query/hypernova/storeHypernovaResults.js @@ -1,28 +1,33 @@ import applyProps from '../lib/applyProps.js'; -import AggregateFilters from './aggregateFilters.js'; +import AggregateFilters from './aggregateSearchFilters.js'; +import assemble from './assembler.js'; -export default function storeHypernovaResults(collectionNode, userId) { - if (collectionNode.parent.results.length === 0) { - return collectionNode.results = []; +export default function storeHypernovaResults(childCollectionNode, userId) { + if (childCollectionNode.parent.results.length === 0) { + return childCollectionNode.results = []; } - let {filters, options} = applyProps(collectionNode); + let {filters, options} = applyProps(childCollectionNode); - const aggregateFilters = new AggregateFilters(collectionNode); - const linker = collectionNode.linker; + const aggregateFilters = new AggregateFilters(childCollectionNode); + const linker = childCollectionNode.linker; const isVirtual = linker.isVirtual(); + const collection = childCollectionNode.collection; _.extend(filters, aggregateFilters.create()); // for one, one-meta, virtual or not, there is no need for aggregate query. // same rule applies for many, many-meta but no virtual - const collection = collectionNode.collection; - if (linker.isSingle() || (linker.isMany() && !isVirtual)) { + if (!isVirtual) { + const filteredOptions = _.omit(options, 'limit'); + if (collection.findSecure) { - return collection.findSecure(filters, {}, userId).fetch(); + childCollectionNode.results = collection.findSecure(filters, filteredOptions, userId).fetch(); } else { - return collection.find(filters, {}, userId).fetch(); + childCollectionNode.results = collection.find(filters, filteredOptions, userId).fetch(); } + + assemble(childCollectionNode); } // many, many-meta and virtual arrive here @@ -66,18 +71,26 @@ export default function storeHypernovaResults(collectionNode, userId) { pipeline.push({ $project: { - _id: '$' + _id, + _id: 1, data: {$slice} } }) } - const result = collectionNode.collection.aggregate(pipeline, {explains: true}); - + const aggregateResults = childCollectionNode.collection.aggregate(pipeline, {explains: true}); let results = []; - _.each(result, aggregateResult => { + + _.each(aggregateResults, aggregateResult => { + const parentResult = _.find(childCollectionNode.parent.results, (result) => { + return result._id === aggregateResult._id; + }); + + if (parentResult) { + parentResult[childCollectionNode.linkName] = aggregateResult.data; + } + _.each(aggregateResult.data, item => results.push(item)) }); - collectionNode.results = results; + childCollectionNode.results = results; } \ No newline at end of file diff --git a/lib/query/lib/recursiveFetch.js b/lib/query/lib/recursiveFetch.js index 7e0ec41..9d9c957 100644 --- a/lib/query/lib/recursiveFetch.js +++ b/lib/query/lib/recursiveFetch.js @@ -24,15 +24,11 @@ export default function fetch(node, parentObject, userId) { _.extend(filters, createSearchFilters(parentObject, fieldStorage, strategy, isVirtual)); - //if (node.collection._name === null) { - // results = sift(filters, node.results); - //} else { if (node.collection.findSecure) { results = node.collection.findSecure(filters, options, userId).fetch(); } else { results = node.collection.find(filters, options).fetch(); } - //} } } else { if (node.collection.findSecure) { diff --git a/lib/query/nodes/collectionNode.js b/lib/query/nodes/collectionNode.js index 4760e4e..20a9b70 100644 --- a/lib/query/nodes/collectionNode.js +++ b/lib/query/nodes/collectionNode.js @@ -4,14 +4,11 @@ export default class CollectionNode { constructor(collection, body, linkName) { this.linkName = linkName; this.nodes = []; - this.originalCollection = this.collection = collection; + this.collection = collection; this.body = body; this.props = {}; this.parent = null; this.linker = null; - - this._results = []; - this.localCollection = new Mongo.Collection(null); } get collectionNodes() { @@ -22,22 +19,6 @@ export default class CollectionNode { return _.filter(this.nodes, n => n instanceof FieldNode); } - get results() { - //return this._results; - return this.localCollection.find().fetch(); - } - - set results(objects) { - //return this._results = objects; - let start = new Date(); - _.each(objects, object => { - this.localCollection.insert(object); - }) - let end = new Date(); - - console.log(`inserted ${objects.length} docs in ${end.getTime() - start.getTime()}`); - } - hasGlobalFieldNode() { return !!_.find(this.fieldNodes, n => n.isGlobal()); } diff --git a/lib/query/query.js b/lib/query/query.js index 2921f53..414f776 100644 --- a/lib/query/query.js +++ b/lib/query/query.js @@ -81,7 +81,7 @@ export default class Query { applyFilterFunction(this.body, this.params) ); - return hypernova(node, options.userId); + //return hypernova(node, options.userId); return recursiveFetch(node, null, options.userId); }