Sails workaround for deep populate

2020-03-04 08:50发布

问题:

I'm trying to deep populate a collection.

For example

// UnitType.js
name: { type: 'string' }

// Unit.js
unitType: {
  model: 'unitType',
  via: '_id',
  required: true,
  index: true
}

// Product.js
unit: {
  model: 'unit',
  via: '_id',
  required: true,
  index: true
},

The problem is, that - as far I know from internet research deep populate like

Product.find().populate('unit.unitType');

is currently not supported in sails. To achieve the result I want I currently

  • query Products with populate unit
  • query UnitTypes with the id from `product.unit.unitType``
  • .map() product.unit.unitType with the response

This is of course far from ideal. I also tried using toJSON in the model to "pre-populate" the unitType -> doesn't work since this doesn't support Promises.

There are quite a few threads on so and PR's on github on this issue, but so far I haven't found a solution to this problem. Is there any way to make this better?

回答1:

You could try to replace Waterline ORM with Offshore ORM. There is a hook for sails to do that - sails-hook-orm-offshore.

It's quite easy to implement to your existing project, because its fork of Waterline wits some more features. Only cons i found is that sails-hook-validation stopped working.

How to install

npm install sails-hook-orm-offshore --save

Configuration

.sailsrc

{
    "hooks": {
        "orm": false,
        "pubsub": false
    }
}

Defaults

config/globals.js

adapters: true,
models: true

Usage

Now you will be allowed to deep populate in your queries. For example (from documentation):

User.find()
.populate('foo.bar', { name: 'foo' }) //populate foo into user and bar into foo
.exec(function(err, users) {
    console.log(users[0].foo.bar.name) // 'foo'
});

Second option

Merge deep populate with waterline

npm i Atlantis-Software/waterline#deepPopulate