mirror of
https://github.com/vale981/grapher
synced 2025-03-05 09:31:42 -05:00
fixed to pass tests
This commit is contained in:
parent
233a074dab
commit
d5f8eeaf49
13 changed files with 100 additions and 60 deletions
|
@ -43,10 +43,14 @@ export default class Exposure {
|
|||
const firewall = this.firewall;
|
||||
|
||||
if (firewall) {
|
||||
collection.findSecure = (filters, options, userId) => {
|
||||
collection.firewall = (filters, options, userId) => {
|
||||
if (userId !== undefined) {
|
||||
firewall(filters, options, userId);
|
||||
}
|
||||
};
|
||||
|
||||
collection.findSecure = (filters, options, userId) => {
|
||||
collection.firewall(filters, options, userId);
|
||||
|
||||
return collection.find(filters, options);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,11 @@ export default new SimpleSchema({
|
|||
type: Boolean,
|
||||
defaultValue: false,
|
||||
optional: true
|
||||
},
|
||||
unique: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
optional: true
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -20,19 +20,19 @@ export default function createSearchFilters(object, fieldStorage, strategy, isVi
|
|||
}
|
||||
}
|
||||
|
||||
function createOne(object, fieldStorage) {
|
||||
export function createOne(object, fieldStorage) {
|
||||
return {
|
||||
_id: object[fieldStorage]
|
||||
};
|
||||
}
|
||||
|
||||
function createOneVirtual(object, fieldStorage) {
|
||||
export function createOneVirtual(object, fieldStorage) {
|
||||
return {
|
||||
[fieldStorage]: object._id
|
||||
};
|
||||
}
|
||||
|
||||
function createOneMeta(object, fieldStorage) {
|
||||
export function createOneMeta(object, fieldStorage) {
|
||||
const value = object[fieldStorage];
|
||||
|
||||
return {
|
||||
|
@ -40,13 +40,13 @@ function createOneMeta(object, fieldStorage) {
|
|||
};
|
||||
}
|
||||
|
||||
function createOneMetaVirtual(object, fieldStorage) {
|
||||
export function createOneMetaVirtual(object, fieldStorage) {
|
||||
return {
|
||||
[fieldStorage + '._id']: object._id
|
||||
};
|
||||
}
|
||||
|
||||
function createMany(object, fieldStorage) {
|
||||
export function createMany(object, fieldStorage) {
|
||||
return {
|
||||
_id: {
|
||||
$in: object[fieldStorage] || []
|
||||
|
@ -54,13 +54,13 @@ function createMany(object, fieldStorage) {
|
|||
};
|
||||
}
|
||||
|
||||
function createManyVirtual(object, fieldStorage) {
|
||||
export function createManyVirtual(object, fieldStorage) {
|
||||
return {
|
||||
[fieldStorage]: object._id
|
||||
};
|
||||
}
|
||||
|
||||
function createManyMeta(object, fieldStorage) {
|
||||
export function createManyMeta(object, fieldStorage) {
|
||||
const value = object[fieldStorage];
|
||||
|
||||
return {
|
||||
|
@ -68,7 +68,7 @@ function createManyMeta(object, fieldStorage) {
|
|||
};
|
||||
}
|
||||
|
||||
function createManyMetaVirtual(object, fieldStorage) {
|
||||
export function createManyMetaVirtual(object, fieldStorage) {
|
||||
return {
|
||||
[fieldStorage + '._id']: object._id
|
||||
};
|
|
@ -66,6 +66,10 @@ export default class Linker {
|
|||
*/
|
||||
get linkStorageField()
|
||||
{
|
||||
if (this.isVirtual()) {
|
||||
return this.linkConfig.relatedLinker.linkConfig.linkStorageField;
|
||||
}
|
||||
|
||||
return this.linkConfig.field;
|
||||
}
|
||||
|
||||
|
@ -264,15 +268,42 @@ export default class Linker {
|
|||
}
|
||||
|
||||
_initIndex() {
|
||||
if (Meteor.isServer && this.linkConfig.index) {
|
||||
if (Meteor.isServer) {
|
||||
let field = this.linkConfig.field;
|
||||
if (this.linkConfig.metadata) {
|
||||
field = field + '._id';
|
||||
field = field + '._id';
|
||||
}
|
||||
|
||||
this.mainCollection._ensureIndex({
|
||||
[field]: 1
|
||||
})
|
||||
if (this.linkConfig.index) {
|
||||
if (this.isVirtual()) {
|
||||
throw new Meteor.Error('You cannot set index on an inversed link.');
|
||||
}
|
||||
|
||||
let options;
|
||||
if (this.linkConfig.unique) {
|
||||
if (this.isMany()) {
|
||||
throw new Meteor.Error('You cannot set unique property on a multi field.');
|
||||
}
|
||||
|
||||
options = {unique: true}
|
||||
}
|
||||
|
||||
this.mainCollection._ensureIndex({[field]: 1}, options);
|
||||
} else {
|
||||
if (this.linkConfig.unique) {
|
||||
if (this.isVirtual()) {
|
||||
throw new Meteor.Error('You cannot set unique property on an inversed link.');
|
||||
}
|
||||
|
||||
if (this.isMany()) {
|
||||
throw new Meteor.Error('You cannot set unique property on a multi field.');
|
||||
}
|
||||
|
||||
this.mainCollection._ensureIndex({
|
||||
[field]: 1
|
||||
}, {unique: true})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,7 @@ export default class AggregateFilters {
|
|||
|
||||
this.isVirtual = this.linker.isVirtual();
|
||||
|
||||
if (this.isVirtual) {
|
||||
this.linkStorageField = this.linker.linkConfig.relatedLinker.linkStorageField;
|
||||
} else {
|
||||
this.linkStorageField = this.linker.linkStorageField;
|
||||
}
|
||||
this.linkStorageField = this.linker.linkStorageField;
|
||||
}
|
||||
|
||||
get parentObjects() {
|
||||
|
|
|
@ -1,25 +1,36 @@
|
|||
import createSearchFilters from './createSearchFilters';
|
||||
import createSearchFilters from '../../links/lib/createSearchFilters';
|
||||
import sift from 'sift';
|
||||
|
||||
export default (childCollectionNode) => {
|
||||
export default (childCollectionNode, limit) => {
|
||||
const parent = childCollectionNode.parent;
|
||||
const linker = childCollectionNode.linker;
|
||||
|
||||
const strategy = childCollectionNode.linker.strategy;
|
||||
const isVirtual = childCollectionNode.linker.isVirtual();
|
||||
const fieldStorage = (isVirtual)
|
||||
? childCollectionNode.linker.linkConfig.relatedLinker.linkStorageField
|
||||
: childCollectionNode.linker.linkStorageField;
|
||||
const strategy = linker.strategy;
|
||||
const isVirtual = linker.isVirtual();
|
||||
const isSingle = linker.isSingle();
|
||||
const oneResult = (isVirtual && linker.linkConfig.relatedLinker.linkConfig.unique)
|
||||
|| (!isVirtual) && isSingle;
|
||||
|
||||
const fieldStorage = linker.linkStorageField;
|
||||
|
||||
_.each(parent.results, result => {
|
||||
result[childCollectionNode.linkName] = assembleData(childCollectionNode, result, {
|
||||
fieldStorage, strategy, isVirtual
|
||||
})
|
||||
})
|
||||
fieldStorage, strategy, isVirtual, isSingle, oneResult, limit
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function assembleData(childCollectionNode, result, {fieldStorage, strategy, isVirtual}) {
|
||||
|
||||
function assembleData(childCollectionNode, result, {fieldStorage, strategy, isVirtual, oneResult, limit}) {
|
||||
const filters = createSearchFilters(result, fieldStorage, strategy, isVirtual);
|
||||
const data = sift(filters, childCollectionNode.results);
|
||||
|
||||
return sift(filters, childCollectionNode.results);
|
||||
if (limit) {
|
||||
return data.slice(limit);
|
||||
}
|
||||
|
||||
if (oneResult) {
|
||||
return _.first(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
|
@ -11,15 +11,12 @@ function hypernova(collectionNode, userId) {
|
|||
_.each(collectionNode.results, result => {
|
||||
const accessor = childCollectionNode.linker.createLink(result);
|
||||
|
||||
childCollectionNode.results = accessor.find(filters, options);
|
||||
result[childCollectionNode.linkName] = accessor.find(filters, options);
|
||||
});
|
||||
} else {
|
||||
storeHypernovaResults(childCollectionNode, userId);
|
||||
|
||||
let start = new Date();
|
||||
hypernova(childCollectionNode, userId);
|
||||
let end = new Date();
|
||||
console.log(`hypernova: ${end.getTime() - start.getTime()}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,8 +16,7 @@ export default function storeHypernovaResults(childCollectionNode, userId) {
|
|||
|
||||
_.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
|
||||
// if it's not virtual then we retrieve them and assemble them here.
|
||||
if (!isVirtual) {
|
||||
const filteredOptions = _.omit(options, 'limit');
|
||||
|
||||
|
@ -28,11 +27,17 @@ export default function storeHypernovaResults(childCollectionNode, userId) {
|
|||
}
|
||||
|
||||
assemble(childCollectionNode);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// many, many-meta and virtual arrive here
|
||||
// virtuals arrive here
|
||||
let pipeline = [];
|
||||
|
||||
if (collection.firewall) {
|
||||
collection.firewall(filters, options, userId);
|
||||
}
|
||||
|
||||
pipeline.push({$match: filters});
|
||||
|
||||
if (options.sort) {
|
||||
|
|
|
@ -14,7 +14,7 @@ export default function compose(node, userId) {
|
|||
if (linker.isVirtual()) {
|
||||
options.fields = options.fields || {};
|
||||
_.extend(options.fields, {
|
||||
[linker.linkConfig.relatedLinker.linkStorageField]: 1
|
||||
[linker.linkStorageField]: 1
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import applyProps from './applyProps.js';
|
||||
import createSearchFilters from '../hypernova/createSearchFilters.js';
|
||||
import createSearchFilters from '../../links/lib/createSearchFilters.js';
|
||||
import LinkResolve from '../../links/linkTypes/linkResolve.js';
|
||||
import sift from 'sift';
|
||||
|
||||
|
@ -11,24 +11,21 @@ export default function fetch(node, parentObject, userId) {
|
|||
if (parentObject) {
|
||||
if (node.linker.isResolver()) {
|
||||
let accessor = node.linker.createLink(parentObject, node.collection);
|
||||
|
||||
if (accessor instanceof LinkResolve) {
|
||||
accessor.object = node.parent.collection.findOne(parentObject._id);
|
||||
}
|
||||
accessor.object = node.parent.collection.findOne(parentObject._id);
|
||||
|
||||
results = accessor.fetch(filters, options, userId);
|
||||
} else {
|
||||
const strategy = node.linker.strategy;
|
||||
const isVirtual = node.linker.isVirtual();
|
||||
const fieldStorage = (isVirtual) ? node.linker.linkConfig.relatedLinker.linkStorageField : node.linker.linkStorageField;
|
||||
const fieldStorage = node.linker.linkStorageField;
|
||||
|
||||
_.extend(filters, createSearchFilters(parentObject, fieldStorage, strategy, isVirtual));
|
||||
|
||||
if (node.collection.findSecure) {
|
||||
results = node.collection.findSecure(filters, options, userId).fetch();
|
||||
} else {
|
||||
results = node.collection.find(filters, options).fetch();
|
||||
}
|
||||
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) {
|
||||
|
@ -38,7 +35,6 @@ export default function fetch(node, parentObject, userId) {
|
|||
}
|
||||
}
|
||||
|
||||
// merge filters
|
||||
_.each(results, result => {
|
||||
_.each(node.collectionNodes, collectionNode => {
|
||||
result[collectionNode.linkName] = fetch(collectionNode, result, userId);
|
||||
|
@ -46,7 +42,5 @@ export default function fetch(node, parentObject, userId) {
|
|||
})
|
||||
});
|
||||
|
||||
// assemble filters
|
||||
|
||||
return results;
|
||||
}
|
||||
|
|
|
@ -81,9 +81,7 @@ export default class Query {
|
|||
applyFilterFunction(this.body, this.params)
|
||||
);
|
||||
|
||||
//return hypernova(node, options.userId);
|
||||
|
||||
return recursiveFetch(node, null, options.userId);
|
||||
return hypernova(node, options.userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
3
lib/query/tests/bootstrap.js
vendored
3
lib/query/tests/bootstrap.js
vendored
|
@ -17,7 +17,8 @@ PostCollection.addLinks({
|
|||
},
|
||||
author: {
|
||||
collection: AuthorCollection,
|
||||
type: 'one'
|
||||
type: 'one',
|
||||
unique: true
|
||||
},
|
||||
comment_resolve: {
|
||||
resolve(object) {
|
||||
|
|
|
@ -37,8 +37,6 @@ describe('Query Server Tests', function () {
|
|||
assert.isObject(post.author);
|
||||
assert.equal('John McSmithie', post.author.name);
|
||||
|
||||
assert.lengthOf(post.comment_resolve, 1);
|
||||
|
||||
_.each(post.comments, comment => {
|
||||
assert.isString(comment.author.name);
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue