Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Projections #1310

Merged
merged 16 commits into from
Mar 17, 2016
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 55 additions & 37 deletions lib/waterline/query/deferred.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ Deferred.prototype.populate = function(keyName, criteria) {
});
return this;
}

// Normalize sub-criteria
try {
criteria = normalize.criteria(criteria);
Expand Down Expand Up @@ -149,32 +149,6 @@ Deferred.prototype.populate = function(keyName, criteria) {
);
}

//////////////////////////////////////////////////////////////////////
// (there has been significant progress made towards both of these ///
// goals-- contact @mikermcneil if you want to help) /////////////////
//////////////////////////////////////////////////////////////////////
// TODO:
// Create synonym for `.populate()` syntax using criteria object
// syntax. i.e. instead of using `joins` key in criteria object
// at the app level.
//////////////////////////////////////////////////////////////////////
// TODO:
// Support Mongoose-style `foo.bar.baz` syntax for nested `populate`s.
// (or something comparable.)
// One solution would be:
// .populate({
// friends: {
// where: { name: 'mike' },
// populate: {
// dentist: {
// where: { name: 'rob' }
// }
// }
// }
// }, optionalCriteria )
////////////////////////////////////////////////////////////////////


// Grab the key being populated to check if it is a has many to belongs to
// If it's a belongs_to the adapter needs to know that it should replace the foreign key
// with the associated value.
Expand All @@ -187,7 +161,6 @@ Deferred.prototype.populate = function(keyName, criteria) {
parentKey: attr.columnName || pk,
child: attr.references,
childKey: attr.on,
select: Object.keys(this._context.waterline.schema[attr.references].attributes),
alias: keyName,
removeParentKey: !!parentKey.model,
model: !!hasOwnProperty(parentKey, 'model'),
Expand All @@ -196,16 +169,26 @@ Deferred.prototype.populate = function(keyName, criteria) {

// Build select object to use in the integrator
var select = [];
Object.keys(this._context.waterline.schema[attr.references].attributes).forEach(function(key) {
var obj = self._context.waterline.schema[attr.references].attributes[key];
if (!hasOwnProperty(obj, 'columnName')) {
var customSelect = criteria.select && _.isArray(criteria.select);
_.each(this._context.waterline.schema[attr.references].attributes, function(val, key) {
// Check if the user has defined a custom select and if so normalize it
if(customSelect && !_.includes(criteria.select, key)) {
return;
}

if (!_.has(val, 'columnName')) {
select.push(key);
return;
}

select.push(obj.columnName);
select.push(val.columnName);
});

// Ensure the PK and FK are always selected - otherwise things like the
// integrator won't work correctly
select.push(pk);
select.push(attr.on);

join.select = select;

var schema = this._context.waterline.schema[attr.references];
Expand All @@ -226,13 +209,32 @@ Deferred.prototype.populate = function(keyName, criteria) {

// If a junction table is used add an additional join to get the data
if (reference && hasOwnProperty(attr, 'on')) {
// Build out the second join object that will link a junction table with the
// values being populated
var selects = _.map(_.keys(this._context.waterline.schema[reference.references].attributes), function(attr) {
var expandedAttr = self._context.waterline.schema[reference.references].attributes[attr];
return expandedAttr.columnName || attr;
var selects = [];
_.each(this._context.waterline.schema[reference.references].attributes, function(val, key) {
// Check if the user has defined a custom select and if so normalize it
if(customSelect && !_.includes(criteria.select, key)) {
return;
}

if (!_.has(val, 'columnName')) {
selects.push(key);
return;
}

selects.push(val.columnName);
});

// Ensure the PK and FK are always selected - otherwise things like the
// integrator won't work correctly
var childPk;
_.each(this._context.waterline.schema[reference.references].attributes, function(val, key) {
if(_.has(val, 'primaryKey') && val.primaryKey) {
childPk = val.columnName || key;
}
});

selects.push(childPk);

join = {
parent: attr.references,
parentKey: reference.columnName,
Expand Down Expand Up @@ -270,6 +272,22 @@ Deferred.prototype.populate = function(keyName, criteria) {
}
};

/**
* Add projections to the parent
*
* @param {Array} attributes to select
* @return this
*/

Deferred.prototype.select = function(attributes) {
if(!_.isArray(attributes)) {
attributes = [attributes];
}

this._criteria.select = attributes;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should append to existing select and not replace it. Will allow to call select twice.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good call!

return this;
};

/**
* Add a Where clause to the criteria object
*
Expand Down