mirror of
https://github.com/vale981/grapher
synced 2025-03-06 01:51:38 -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;
|
const firewall = this.firewall;
|
||||||
|
|
||||||
if (firewall) {
|
if (firewall) {
|
||||||
collection.findSecure = (filters, options, userId) => {
|
collection.firewall = (filters, options, userId) => {
|
||||||
if (userId !== undefined) {
|
if (userId !== undefined) {
|
||||||
firewall(filters, options, userId);
|
firewall(filters, options, userId);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
collection.findSecure = (filters, options, userId) => {
|
||||||
|
collection.firewall(filters, options, userId);
|
||||||
|
|
||||||
return collection.find(filters, options);
|
return collection.find(filters, options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,11 @@ export default new SimpleSchema({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
optional: true
|
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 {
|
return {
|
||||||
_id: object[fieldStorage]
|
_id: object[fieldStorage]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOneVirtual(object, fieldStorage) {
|
export function createOneVirtual(object, fieldStorage) {
|
||||||
return {
|
return {
|
||||||
[fieldStorage]: object._id
|
[fieldStorage]: object._id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOneMeta(object, fieldStorage) {
|
export function createOneMeta(object, fieldStorage) {
|
||||||
const value = object[fieldStorage];
|
const value = object[fieldStorage];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -40,13 +40,13 @@ function createOneMeta(object, fieldStorage) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOneMetaVirtual(object, fieldStorage) {
|
export function createOneMetaVirtual(object, fieldStorage) {
|
||||||
return {
|
return {
|
||||||
[fieldStorage + '._id']: object._id
|
[fieldStorage + '._id']: object._id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMany(object, fieldStorage) {
|
export function createMany(object, fieldStorage) {
|
||||||
return {
|
return {
|
||||||
_id: {
|
_id: {
|
||||||
$in: object[fieldStorage] || []
|
$in: object[fieldStorage] || []
|
||||||
|
@ -54,13 +54,13 @@ function createMany(object, fieldStorage) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createManyVirtual(object, fieldStorage) {
|
export function createManyVirtual(object, fieldStorage) {
|
||||||
return {
|
return {
|
||||||
[fieldStorage]: object._id
|
[fieldStorage]: object._id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createManyMeta(object, fieldStorage) {
|
export function createManyMeta(object, fieldStorage) {
|
||||||
const value = object[fieldStorage];
|
const value = object[fieldStorage];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -68,7 +68,7 @@ function createManyMeta(object, fieldStorage) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createManyMetaVirtual(object, fieldStorage) {
|
export function createManyMetaVirtual(object, fieldStorage) {
|
||||||
return {
|
return {
|
||||||
[fieldStorage + '._id']: object._id
|
[fieldStorage + '._id']: object._id
|
||||||
};
|
};
|
|
@ -66,6 +66,10 @@ export default class Linker {
|
||||||
*/
|
*/
|
||||||
get linkStorageField()
|
get linkStorageField()
|
||||||
{
|
{
|
||||||
|
if (this.isVirtual()) {
|
||||||
|
return this.linkConfig.relatedLinker.linkConfig.linkStorageField;
|
||||||
|
}
|
||||||
|
|
||||||
return this.linkConfig.field;
|
return this.linkConfig.field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,15 +268,42 @@ export default class Linker {
|
||||||
}
|
}
|
||||||
|
|
||||||
_initIndex() {
|
_initIndex() {
|
||||||
if (Meteor.isServer && this.linkConfig.index) {
|
if (Meteor.isServer) {
|
||||||
let field = this.linkConfig.field;
|
let field = this.linkConfig.field;
|
||||||
if (this.linkConfig.metadata) {
|
if (this.linkConfig.metadata) {
|
||||||
field = field + '._id';
|
field = field + '._id';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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({
|
this.mainCollection._ensureIndex({
|
||||||
[field]: 1
|
[field]: 1
|
||||||
})
|
}, {unique: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,8 @@ export default class AggregateFilters {
|
||||||
|
|
||||||
this.isVirtual = this.linker.isVirtual();
|
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() {
|
get parentObjects() {
|
||||||
return this.collectionNode.parent.results;
|
return this.collectionNode.parent.results;
|
||||||
|
|
|
@ -1,25 +1,36 @@
|
||||||
import createSearchFilters from './createSearchFilters';
|
import createSearchFilters from '../../links/lib/createSearchFilters';
|
||||||
import sift from 'sift';
|
import sift from 'sift';
|
||||||
|
|
||||||
export default (childCollectionNode) => {
|
export default (childCollectionNode, limit) => {
|
||||||
const parent = childCollectionNode.parent;
|
const parent = childCollectionNode.parent;
|
||||||
|
const linker = childCollectionNode.linker;
|
||||||
|
|
||||||
const strategy = childCollectionNode.linker.strategy;
|
const strategy = linker.strategy;
|
||||||
const isVirtual = childCollectionNode.linker.isVirtual();
|
const isVirtual = linker.isVirtual();
|
||||||
const fieldStorage = (isVirtual)
|
const isSingle = linker.isSingle();
|
||||||
? childCollectionNode.linker.linkConfig.relatedLinker.linkStorageField
|
const oneResult = (isVirtual && linker.linkConfig.relatedLinker.linkConfig.unique)
|
||||||
: childCollectionNode.linker.linkStorageField;
|
|| (!isVirtual) && isSingle;
|
||||||
|
|
||||||
|
const fieldStorage = linker.linkStorageField;
|
||||||
|
|
||||||
_.each(parent.results, result => {
|
_.each(parent.results, result => {
|
||||||
result[childCollectionNode.linkName] = assembleData(childCollectionNode, 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 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 => {
|
_.each(collectionNode.results, result => {
|
||||||
const accessor = childCollectionNode.linker.createLink(result);
|
const accessor = childCollectionNode.linker.createLink(result);
|
||||||
|
|
||||||
childCollectionNode.results = accessor.find(filters, options);
|
result[childCollectionNode.linkName] = accessor.find(filters, options);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
storeHypernovaResults(childCollectionNode, userId);
|
storeHypernovaResults(childCollectionNode, userId);
|
||||||
|
|
||||||
let start = new Date();
|
|
||||||
hypernova(childCollectionNode, userId);
|
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());
|
_.extend(filters, aggregateFilters.create());
|
||||||
|
|
||||||
// for one, one-meta, virtual or not, there is no need for aggregate query.
|
// if it's not virtual then we retrieve them and assemble them here.
|
||||||
// same rule applies for many, many-meta but no virtual
|
|
||||||
if (!isVirtual) {
|
if (!isVirtual) {
|
||||||
const filteredOptions = _.omit(options, 'limit');
|
const filteredOptions = _.omit(options, 'limit');
|
||||||
|
|
||||||
|
@ -28,11 +27,17 @@ export default function storeHypernovaResults(childCollectionNode, userId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assemble(childCollectionNode);
|
assemble(childCollectionNode);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// many, many-meta and virtual arrive here
|
// virtuals arrive here
|
||||||
let pipeline = [];
|
let pipeline = [];
|
||||||
|
|
||||||
|
if (collection.firewall) {
|
||||||
|
collection.firewall(filters, options, userId);
|
||||||
|
}
|
||||||
|
|
||||||
pipeline.push({$match: filters});
|
pipeline.push({$match: filters});
|
||||||
|
|
||||||
if (options.sort) {
|
if (options.sort) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default function compose(node, userId) {
|
||||||
if (linker.isVirtual()) {
|
if (linker.isVirtual()) {
|
||||||
options.fields = options.fields || {};
|
options.fields = options.fields || {};
|
||||||
_.extend(options.fields, {
|
_.extend(options.fields, {
|
||||||
[linker.linkConfig.relatedLinker.linkStorageField]: 1
|
[linker.linkStorageField]: 1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import applyProps from './applyProps.js';
|
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 LinkResolve from '../../links/linkTypes/linkResolve.js';
|
||||||
import sift from 'sift';
|
import sift from 'sift';
|
||||||
|
|
||||||
|
@ -11,16 +11,13 @@ export default function fetch(node, parentObject, userId) {
|
||||||
if (parentObject) {
|
if (parentObject) {
|
||||||
if (node.linker.isResolver()) {
|
if (node.linker.isResolver()) {
|
||||||
let accessor = node.linker.createLink(parentObject, node.collection);
|
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);
|
results = accessor.fetch(filters, options, userId);
|
||||||
} else {
|
} else {
|
||||||
const strategy = node.linker.strategy;
|
const strategy = node.linker.strategy;
|
||||||
const isVirtual = node.linker.isVirtual();
|
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));
|
_.extend(filters, createSearchFilters(parentObject, fieldStorage, strategy, isVirtual));
|
||||||
|
|
||||||
|
@ -38,7 +35,6 @@ export default function fetch(node, parentObject, userId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge filters
|
|
||||||
_.each(results, result => {
|
_.each(results, result => {
|
||||||
_.each(node.collectionNodes, collectionNode => {
|
_.each(node.collectionNodes, collectionNode => {
|
||||||
result[collectionNode.linkName] = fetch(collectionNode, result, userId);
|
result[collectionNode.linkName] = fetch(collectionNode, result, userId);
|
||||||
|
@ -46,7 +42,5 @@ export default function fetch(node, parentObject, userId) {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
// assemble filters
|
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,7 @@ export default class Query {
|
||||||
applyFilterFunction(this.body, this.params)
|
applyFilterFunction(this.body, this.params)
|
||||||
);
|
);
|
||||||
|
|
||||||
//return hypernova(node, options.userId);
|
return hypernova(node, options.userId);
|
||||||
|
|
||||||
return recursiveFetch(node, null, options.userId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
lib/query/tests/bootstrap.js
vendored
3
lib/query/tests/bootstrap.js
vendored
|
@ -17,7 +17,8 @@ PostCollection.addLinks({
|
||||||
},
|
},
|
||||||
author: {
|
author: {
|
||||||
collection: AuthorCollection,
|
collection: AuthorCollection,
|
||||||
type: 'one'
|
type: 'one',
|
||||||
|
unique: true
|
||||||
},
|
},
|
||||||
comment_resolve: {
|
comment_resolve: {
|
||||||
resolve(object) {
|
resolve(object) {
|
||||||
|
|
|
@ -37,8 +37,6 @@ describe('Query Server Tests', function () {
|
||||||
assert.isObject(post.author);
|
assert.isObject(post.author);
|
||||||
assert.equal('John McSmithie', post.author.name);
|
assert.equal('John McSmithie', post.author.name);
|
||||||
|
|
||||||
assert.lengthOf(post.comment_resolve, 1);
|
|
||||||
|
|
||||||
_.each(post.comments, comment => {
|
_.each(post.comments, comment => {
|
||||||
assert.isString(comment.author.name);
|
assert.isString(comment.author.name);
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Reference in a new issue