3
votes

I have looked at a lot of old SO questions which have broken GitHub links and SailsJS Trello, however I am still unclear.

Is it possible, to populate a field (one-to-one relationship) in SailsJS and return only specific fields (either via select or omit).

await Document.find({id: id}).populate('createdBy', {select: ['name']})

I am getting

UsageError: Invalid populate(s).
Details:
  Could not populate `createdBy` because of ambiguous usage.  This is a singular ("model") association, which means it never refers to more than _one_ associated record.  So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association
, since it generally wouldn't make any sense.  But that's the trouble-- it looks like some sort of a subcriteria (or something) _was_ provided!
(Note that subcriterias consisting ONLY of `omit` or `select` are a special case that _does_ make sense.  This usage will be supported in a future version of Waterline.)

Here's what was passed in:
{ select: [ 'name' ] }

In models,

createdBy: {
      model: 'user',
      description: 'Who is this document assigned to'
    },

I am using sails 1.1.0, waterline 0.13.5-0

Am I doing this right? Is there a way to do this?

2

2 Answers

2
votes

I solved the problem and made a pull request. Since the pull request has not yet been accepted, be careful and use it on your ask.

Go to

node_modules/waterline/lib/waterline/utils/query/forge-stage-two-query.js

Go to this section

// If this is a singular ("model") association, then it should always have
// an empty dictionary on the RHS.  (For this type of association, there is
// always either exactly one associated record, or none of them.)
if (populateAttrDef.model) {....}

Change it to:

     if (populateAttrDef.model) {

        // Tolerate a subcriteria of `{}`, interpreting it to mean that there is
        // really no criteria at all, and that we should just use `true` (the
        // default "enabled" value for singular "model" associations.)
        if (_.isEqual(query.populates[populateAttrName], {})) {
          query.populates[populateAttrName] = true;
        }
        // Otherwise, this simply must be `true`.  Otherwise it's invalid.
        else {

          if (query.populates[populateAttrName] !== true && (_.isUndefined(query.populates[populateAttrName].select) && _.isUndefined(query.populates[populateAttrName].omit))) {
            throw buildUsageError(
              'E_INVALID_POPULATES',
              'Could not populate `'+populateAttrName+'` because of ambiguous usage.  '+
              'This is a singular ("model") association, which means it never refers to '+
              'more than _one_ associated record.  So passing in subcriteria (i.e. as '+
              'the second argument to `.populate()`) is not supported for this association, '+
              'since it generally wouldn\'t make any sense.  But that\'s the trouble-- it '+
              'looks like some sort of a subcriteria (or something) _was_ provided!\n'+
              '(Note that subcriterias consisting ONLY of `omit` or `select` are a special '+
              'case that _does_ make sense.  This usage will be supported in a future version '+
              'of Waterline.)\n'+
              '\n'+
              'Here\'s what was passed in:\n'+
              util.inspect(query.populates[populateAttrName], {depth: 5}),
              query.using
            );
          }//-•
          else {
            query.populates[populateAttrName] = {
              select: query.populates[populateAttrName].select? query.populates[populateAttrName].select : undefined,
              omit: query.populates[populateAttrName].omit? query.populates[populateAttrName].omit : undefined
            };
          }

        }//>-•

      }

This is the pull request to see exactly what you should change: https://github.com/balderdashy/waterline/pull/1613

1
votes

When u use One-to-one association u can't use subcriteria like error say.

So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association

U can use customToJSON function on model createdBy to omit data.

customToJSON: function() {

  return _.omit(this, ['createdAt', 'updatedAt', 'id'])
}