fixed to pass tests

This commit is contained in:
Theodor Diaconu 2016-09-22 13:46:27 +03:00
parent 233a074dab
commit d5f8eeaf49
13 changed files with 100 additions and 60 deletions

View file

@ -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);
}

View file

@ -35,6 +35,11 @@ export default new SimpleSchema({
type: Boolean,
defaultValue: false,
optional: true
},
unique: {
type: Boolean,
defaultValue: false,
optional: true
}
});

View file

@ -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
};

View file

@ -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})
}
}
}
}

View file

@ -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() {

View file

@ -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;
}

View file

@ -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()}`);
}
});
}

View file

@ -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) {

View file

@ -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
});
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -17,7 +17,8 @@ PostCollection.addLinks({
},
author: {
collection: AuthorCollection,
type: 'one'
type: 'one',
unique: true
},
comment_resolve: {
resolve(object) {

View file

@ -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);
})